Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Only cover scope boundaries in the parent layer if there is a scope boundary in the injected layer #19726
#19556 introduced new behavior for scopes from injected grammars, causing them to "cover" or "shadow" scope boundaries in the parent grammar. This was added to prevent duplicated and conflicted scope boundaries from being rendered in cases where the syntax tree of a parent grammar contains nodes that overlap with the syntax tree of the child grammar. See the body of #19556 for more details.
The solution in this PR is to only hide scopes from the parent grammar in situations where the child grammar's
In the process of exploring this issue, it occurred to @maxbrunsfeld and I that there might be more diabolical cases where a node in the child grammar shadows only a close tag in the parent grammar. However, this actually seems unlikely. If we shadow a scope close at a given position, there's a high probability that we also shadow the scope open due to the structure of the syntax tree, thus preventing an unbalanced scope open from occurring. In the event we encounter an actual case of an unbalanced tag caused by shadowing, we will have more information on which to base a solution. In the meantime, the hypothetical possibility doesn't justify the complexity of a full solution.
as-cii left a comment •
It seems like in the current situation we sometimes allow for a shallower grammar to emit scopes even when a deeper grammar is parked at the same position. If I understand correctly, this may lead to one of those diabolical scenarios you and @maxbrunsfeld illustrated in the body of this pull request in which we could close a tag that was never opened (or vice versa).
If that's correct, I wanted to mention a couple of observations (which we may want to address later, if ever at all) about the invariants of the injection system. I am not super familiar with this mechanism in general, so pardon my ignorance on the subject.
Either way, this seems like a reasonable workaround to me and I am totally cool with shipping it as it is until we gather more real-world examples to drive a more general solution.
Jul 30, 2019
1 check passed
Just some additional thoughts on this:
Recap - Right now, we "cover up" scope start events from shallower layers if a deeper layer has a scope start event at the same position, and similarly for scope end events. This PR fixes a problem where we were incorrectly covering up a scope end event that should not have been covered.
Remaining Error Case - It's still theoretically possible that we might incorrectly "cover up" a closing scope, leading to a similar kind of scope "spillage" that happened in #19582. It could happen in a situation like this diagram, in which curly braces represent scope boundaries:
In the outer layer (layer-1) a scope contains
Possible Solution - I think that to solve this (theoretical) problem, we would need to further restrict the criteria for when to "cover up" outer layers' scope boundaries. We should only cover up scope events if the two layers are parked on syntax nodes with the same range (i.e.
I think that this would guarantee that we would only cover closing scopes if we also covered up the opening scopes.