Skip to content

Record syntactic information about modifiers #1608

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 25, 2016

Conversation

liufengyun
Copy link
Contributor

This PR defines trait Mod to record source information about modifiers.

Note that privateWithin is already present in Modifiers, thus it's not repeated in Mod definitions.

Review @odersky .

val flag = flagOfToken(in.token)
val tok = in.token
val flag = flagOfToken(tok)
val mod = atPos(in.offset) { in.nextToken(); modOfToken(tok) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shorter:

val mod = atPos(in.skipToken()) { modOfToken(tok) }

Same for similar places below.

/** Modifiers and annotations for definitions
* @param flags The set flags
object Mod {
case class Private() extends Mod
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My hunch is that this can be done slightly more elegantly as follows:

  • Have Mod take a flags field and have every case class set it. E.g.

       case class Protected() extends Mod(Flags.Protected)
    

Have a new method in Modifiers:

 def | (mod: Mod) =
    withFlags(mod.flags).withAddedMod(mod)

Then, only use | instead of setting flags and mods separately. I believe that would make redundant much of the current code. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea, I'll do as you suggested, thanks a lot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@odersky I just checked the parser code, whether a semantic flag gets added depends on some compatibility check (see addFlag). But the syntactic Mod should be always added.

It's also possible to refactor the flag compatibility check to Modifiers, but the error reporting depends on compiler state (lastErrorOffset), make the refactoring difficult.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@liufengyun I think this can be accommodated in addFlag:

  if (compatible(mods.flags, flag)) mods | mod
  else mods.withAddedMod(mod)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@odersky I just pushed a commit addressing the review feedback. Note that addFlag is also used for non-syntactic flags(such as trait, method), so I added another addMod method.

And it turns out that we always need to check the added flags, thus def | (mod: Mod) = .. is not useful.

@@ -1819,9 +1826,13 @@ object Parsers {
*/
def defOrDcl(start: Int, mods: Modifiers): Tree = in.token match {
case VAL =>
patDefOrDcl(start, posMods(start, mods), in.getDocComment(start))
val mod = atPos(in.skipToken()) { Mod.Val() }
val modPos = atPos(start) { mods.withAddedMod(mod) }
Copy link
Contributor

@odersky odersky Oct 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two comments:

  • Why the name modPos? It reads like "the positon of mod" to me. Maybe use mods1 instead, or inline the expression.
  • I don't think you need an atPos(start) here (and neither for the other occurrences of withAddedMod). The position of the modifiers is set automatically to the union of mods and mod; so you don't need to set the position manually.

Otherwise LGTM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@odersky thanks for letting me know this clever trick in Positioned. I addressed them in the latest commit and rebased.

Note that there's no need to explicitly call `atPos` here, because
the initializer of `Positioned` will automatically synthesize the
initial position from its children elements. Refer to the definition
of `Positioned` for more details.
@odersky
Copy link
Contributor

odersky commented Oct 25, 2016

Good to have this in!

@odersky odersky merged commit 40da850 into scala:master Oct 25, 2016
@allanrenucci allanrenucci deleted the modifiers branch December 14, 2017 19:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants