Skip to content
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

Make 'from' parameter in TokenList.slice/find inclusive #534

Merged
merged 4 commits into from
Jan 4, 2018

Conversation

marcelocenerine
Copy link
Contributor

  • Addresses Make from in TokenList.slice(from, to) inclusive #516. The original goal was to do this only for TokenList.slice but then I realized that find was also inconsistent.

    • find is not used anywhere in the repo
    • slice is used in 2 places: ProcedureSyntax & ExplicitResultTypes. For both of them this change won't cause any harm.
  • Fixes a bug in TokenList.leading that was causing the first element in the token list (usually Token.BOF) being incorrectly dropped.

def leading(token: Token): SeqView[Token, IndexedSeq[Token]] =
tokens.view(0, tok2idx(token)).drop(1).reverse
tokens.view(0, tok2idx(token)).reverse
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe the goal here was to have the token element dropped from the result. However, this is already handled by the .view method as the end parameter is exclusive

Copy link
Contributor

Choose a reason for hiding this comment

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

Woah, this was surprising :D

@     tokens.view(0, tok2idx(token)).reverse.mkString
res19: String = "(list { a object"

@     tokens.view(0, tok2idx(token)).drop(1).reverse.mkString
res20: String = "(list { a object"

Yes, the objective was to drop the token.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

val tokens = "foo bar".tokenize.get
tokens: scala.meta.tokens.Tokens = Tokens(, foo,  , bar, )
val barIdx = 3

tokens.view(0, barIdx).reverse.mkString("|")
res11: String = " |foo|"
tokens.view(0, barIdx).drop(1).reverse.mkString("|")
res12: String = " |foo"

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, drop(1) was removing the BOF token, which is wrong behaviour but probably never surfaced as a problem because it's zero length. Good catch!

Copy link
Contributor

@olafurpg olafurpg left a comment

Choose a reason for hiding this comment

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

Thank you for this contribution @marcelocenerine ! Everything looks good except the slice signature change 👍

def leading(token: Token): SeqView[Token, IndexedSeq[Token]] =
tokens.view(0, tok2idx(token)).drop(1).reverse
tokens.view(0, tok2idx(token)).reverse
Copy link
Contributor

Choose a reason for hiding this comment

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

Woah, this was surprising :D

@     tokens.view(0, tok2idx(token)).reverse.mkString
res19: String = "(list { a object"

@     tokens.view(0, tok2idx(token)).drop(1).reverse.mkString
res20: String = "(list { a object"

Yes, the objective was to drop the token.

}
builder.result()
}
def slice(from: Token, to: Token): SeqView[Token, IndexedSeq[Token]] =
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this signature change necessary? I think we can keep the signature to avoid a binary breaking change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In fact it is not. Given that the method now returns a view, I wanted to make this fact explicit as well as have the return type consistent the leading*/trailing* methods. It wouldn't cause compilation errors but indeed it would break binary compatibility. I'm gonna change it back to Seq to avoid that.

builder.result()
}
def slice(from: Token, to: Token): Seq[Token] =
tokens.view(tok2idx(from), tok2idx(to))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

given that the method no longer says that the returned collection is a view, I was going to change the implementation and delegate to Tokens.slice instead which should be slightly faster as it is backed by an array and does not involve any copying. But then I realized that Tokens.length is buggy, which breaks isEmpty:

"foo".tokenize.get.slice(1, 0).isEmpty
res4: Boolean = false

I'm gonna file an issue or submit a PR to Scalameta.

Copy link
Contributor

Choose a reason for hiding this comment

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

iirc someone reported a similar problem with Tokens.length the other day. Length is implemented like this

  def length: Int = end - start

Should it be this instead?

  def length: Int = math.max(0, end - start)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The root cause is in Tokens.slice: scalameta/scalameta#1207

Copy link
Contributor

@olafurpg olafurpg left a comment

Choose a reason for hiding this comment

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

LGTM 👍 Thank you for fixing this @marcelocenerine

@olafurpg olafurpg merged commit 8cb5a10 into scalacenter:master Jan 4, 2018
@MasseGuillaume MasseGuillaume added this to the v0.5.8 milestone Jan 25, 2018
@marcelocenerine marcelocenerine deleted the slice_from_inclusive branch February 19, 2018 18:48
@olafurpg olafurpg modified the milestones: v0.5.8, v0.6.0-M2 Apr 11, 2018
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