fix: complete backticked idents containing $#11024
Conversation
|
This works in 3.6.3. |
| this(sym.name) = this(sym.name) + toMember(sym, symtpe) | ||
| } else if (!sym.isError && !sym.isArtifact && sym.hasRawInfo) { | ||
| val decodedName = sym.name.decodedName | ||
| if (!decodedName.containsChar('$') || decodedName.encoded == sym.name.toString) { |
There was a problem hiding this comment.
!decodedName.containsChar('$') allows names that have no $ or use encodings like $lt.
decodedName.encoded == sym.name.toString allows names that have a $ but use no encoding.
So, not allowed are names that use an encoding and also have a $. Something like foo$_<. Is that the intention?
There was a problem hiding this comment.
Yeah, that is the intention. Are there ever any non-internal names that would use the encoding and have a $? (Is your foo$_< a legitimate user-writable thing?)
I'm a bit more concerned by the other half of the equation though: are there any internal names where the $ is escaped? I thought there wouldn't be, but there's a test failure around a $init$.
There was a problem hiding this comment.
foo$_< seems to be a legal identifier.
I think instaed of the filter that only disallows these weird identifiers, you could just as well allow any name.
The typical internal names are $outer, g$1 for a nested method g, f$default$1 for a default of method f, $init$ for trait initialization, $anon for methods implementing lambdas, foo$sp$XX for speicalized methods, and many others. Note that constructors have name $lessinit$greater / <init>.
Many of them are probably not a concern because they are created in later phases, I assume the presentation compiler queries the symbol table right after the typer phase. Some are definitely created early, but might have the isArtifact flag which is checked above. You could add another check for sym.isSynthetic, I think this would make sense, it might fix the $init$ case. (Artifact is translated to ACC_SYNTHETIC in bytecode, while synthetic remains a Scala symbol table only flag). Unfortunately the way we apply the artifact and synthetic flags is not very consistent. So if there remain synthetic identifiers that go through, we could add specific filters for those.
There was a problem hiding this comment.
I'll try out removing any $ based checks and see how far I get with the symbol flags.
decodedName.encoded == sym.name.toStringallows names that have a $ but use no encoding.
Probably moot assuming your suggestion works out, but I think I misread this. The intention is that if someone wrote $ in one of their variables it would be encoded, such that if you decode and then re-encode, you'll get the same internal (encoded) representation. OTOH, if an internal name is generated with a $ in its encoded form, then decoding passes the $ through unchanged, but re-encoding escapes it (so the quoted predicate above fails).
I agree this is pretty roundabout. Really I wanted NameTransformer.isInCodomainOfEncode and x.decoded.encoded == x is a poor-man's version of that.
There was a problem hiding this comment.
if someone wrote
$in one of their variables it would be encoded
I think this is not the case, $ is not encoded as it's valid in bytecode.
scala> :power
scala> val n = TermName("$hey")
scala> n.encodedName
val res0: n.ThisNameType = $hey
scala> n.encodedName.decodedName
val res1: $r.intp.global.TermName = $hey
05c069f to
d47b957
Compare
|
@lrytz I think this is ready for review again |
| [inaccessible] private[this] val self: callccInterpreter.type | ||
| [inaccessible] private[this] val self: callccInterpreter.type | ||
| [inaccessible] private[this] val self: callccInterpreter.type | ||
| [inaccessible] private[this] val self: callccInterpreter.type |
There was a problem hiding this comment.
Do you know why these 4x self show up now?
There was a problem hiding this comment.
Yeah, these are the fields you get from implicit classes:
scala.Predef.any2stringaddscala.Predef.StringFormatscala.Predef.Ensuringscala.Predef.ArrowAssoc
In all 4 cases, the implicit class field is called self.
They did not used to show up because the decoded names have dollar signs (I'm guessing this is connected to the fact they're declare in the object Predef, though I didn't look further)
scala$Predef$any2stringadd$$self
scala$Predef$StringFormat$$self
scala$Predef$Ensuring$$self
scala$Predef$ArrowAssoc$$self
There was a problem hiding this comment.
Ah, thanks. I don't have the background why [inaccessible] symbols are included in completions. I wonder if inaccessible symbols of implicit conversion targets should really be there as well, or if that is by mistake.
The scala$Predef$any2stringadd$$self name is an "expanded" name set by sym.makeNotPrivate, sym.hasFlag(EXPANDEDNAME) should be true here.
There was a problem hiding this comment.
The [inaccessible] means that it doesn't actually show up in the completions. These tests have completions that generally do include results that need an implicit conversion, so I think this is the right behavior.
| if ((sym.isGetter || sym.isSetter) && sym.accessed != NoSymbol) { | ||
| add(sym.accessed, pre, implicitlyAdded)(toMember) | ||
| } else if (!sym.name.decodedName.containsName("$") && !sym.isError && !sym.isArtifact && sym.hasRawInfo) { | ||
| } else if (!sym.name.decodedName.startsWith('$') && !sym.isError && !sym.isArtifact && sym.hasRawInfo) { |
There was a problem hiding this comment.
Did you test what happens if the condition is removed entirely? Maybe we can make a more specific filter, e.g. for $init$ and ...?
There was a problem hiding this comment.
Removing the condition causes failures only due to $init$. Full list is just
partest \
/Users/alec/Code/scala/test/files/presentation/infix-completion \
/Users/alec/Code/scala/test/files/presentation/infix-completion2 \
/Users/alec/Code/scala/test/files/presentation/scope-completion-3
Only reason I didn't do that is that when I went into StdNames looking for the right constant against which to compare, I saw a bunch of other names that probably should never be in completions and which start in $. I'm not sure if those are ever going to show up...
scala/src/reflect/scala/reflect/internal/StdNames.scala
Lines 370 to 405 in f87d1a0
If you think just guarding against $init$ is enough, happy to update to that. I only left the startsWith('$') after seeing how many names in the above list start with $...
There was a problem hiding this comment.
Not obvious.. some of these are suffixes. $outer is not, but outer fields are probably added in a later phase. There's also the sym.isArtifact check which should be true for most synthetics, but $init$ seems to be a counter-example.
Since the goal of this PR is to show names containing $, it seems a bit ad-hoc to me to change the filter to startsWith('$'). So maybe it's better to remove it and address new unwanted candidates such as $init$.
There was a problem hiding this comment.
Tried what you suggested out - rather than do anything around '$', I removed the check entirely and added ARTIFACT to $init$. I did a spot check of the other $-containing symbols and AFAICT they most have ARTIFACT set or should not show up in completions for other reasons.
This does mean that more test output changes (at least those that are printing the flags for $init$ defs)
728d49a to
c6db746
Compare
|
I think the CI failure is spurious... |
|
@harpocrates CI is fixed. I might have sent you down the wrong path though. The |
|
Funny that I can buy that What do you propose there? Going back to just checking against the |
Yeah, it's history and probably not worth changing at this point..
Ah.. you're right None of these have the So yes, I think we should go for filtering |
|
Sounds good - doing this now. @lrytz Unrelated, but now that 2.13.17 is in snapshot mode, I get errors trying to compile anything in SBT: I can work around this by rebasing onto an old |
|
I assume you opened the repo in vs code / metals, which added the semanticdb plugin. IIRC metals adds a Or you revert |
Replace the ad-hoc check for hiding from completions identifiers containing a `$` with a check against specific flavours of compiler-generated $-containing names.
c6db746 to
1b0c18f
Compare
lrytz
left a comment
There was a problem hiding this comment.
Thank you! Sorry it was a winding road.
The previous check around filtering out names whose decoded representation contained
$was probably written with the idea being that most dollar signs are just encoding artifacts, however it misses the fact that every once in a blue moon, the decoding result might have a$that was actually written by the user (as opposed to something synthetic likeMODULE$)