Skip to content

Extract out the common portions of the Json and Regex parsing subsystems.#25541

Merged
jmarolf merged 19 commits intodotnet:features/embeddedRegexfrom
CyrusNajmabadi:embeddedLanguages
Apr 2, 2018
Merged

Extract out the common portions of the Json and Regex parsing subsystems.#25541
jmarolf merged 19 commits intodotnet:features/embeddedRegexfrom
CyrusNajmabadi:embeddedLanguages

Conversation

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi commented Mar 16, 2018

Followup to #24111 (Extract out the VirtualChar portion of the Regex and JSON editor work).
Precursor to #23984 (regex parser and corresponding tests) and #24110 (json parser and corresponding tests).

Overall map: #24111 (comment)

[jcouv edited]

}

public override bool Equals(object obj)
=> obj is EmbeddedDiagnostic rd && Equals(rd);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: why rd? I'd expect ed or d

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this used to be RegexDiagnostic before i made it EmbeddedDiagnostic. Will fix :)


public bool Contains(VirtualChar virtualChar)
{
foreach (var child in this)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: this is a bit odd. Why not simply do a for loop and forego the enumerator?
Is the enumerator used elsewhere?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah. we use the enumerator later on when we develop features. Note: we tehcnically could forgo the enumerator and just do the for-loop. But this is similar to how we walk normal SyntaxNodes in the IDE layer and it felt cleaner so that i would not be exposing the internal details of child-counts and slot lookups and whatnot.

Value = value;
}

public bool IsMissing => VirtualChars.IsEmpty;
Copy link
Copy Markdown
Member

@jcouv jcouv Mar 31, 2018

Choose a reason for hiding this comment

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

Is it safe to call .IsEmpty on a default ImmutableArray? Same question for .Length below.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In a SyntaxToken none of these will be empty. I will add checks for that in the constructor.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

#resolved.


public bool IsMissing => VirtualChars.IsEmpty;

public EmbeddedSyntaxToken<TSyntaxKind> AddDiagnosticIfNone(EmbeddedDiagnostic diagnostic)
Copy link
Copy Markdown
Member

@jcouv jcouv Mar 31, 2018

Choose a reason for hiding this comment

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

It looks like this method is not used or tested. If this method is removed, then WithDiagnostics can probably be removed too and possibly With as well.

Update: Hum, I just realized the tests are not in this PR... Can the relevant tests be moved into this PR along with the code change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The tests are in another PR because they destroy github. You can see the tests for regex and json in these PRs:

#25520

I would prefer to keep them separate.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Also note: this is hte common embedded languages subsystem part of the work. There are no explicit tests for this part as this is just an implementation detail of hte final regex parser/features.

public readonly ImmutableArray<VirtualChar> VirtualChars;
public readonly ImmutableArray<EmbeddedSyntaxTrivia<TSyntaxKind>> TrailingTrivia;
internal readonly ImmutableArray<EmbeddedDiagnostic> Diagnostics;
public readonly object Value;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's not obvious to me what the Value is for. Consider commenting.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Will do.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

#resolved.

internal abstract class EmbeddedSyntaxTree<TSyntaxKind, TNode, TRoot>
where TSyntaxKind : struct
where TNode : EmbeddedSyntaxNode<TSyntaxKind, TNode>
where TRoot : TNode
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there a scenario where TRoot is not literally TNode?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes. TRoot is never literally TNode. For regex and json it will be RegexCompilationUnit and JsonCompilationUnit respectively.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Renamed to be clearer. #resolved.

@jcouv jcouv added the Area-IDE label Mar 31, 2018
internal readonly ImmutableArray<EmbeddedDiagnostic> Diagnostics;
public readonly object Value;

public EmbeddedSyntaxToken(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From usage in subsequent PR, it seems that you never put default arrays for those parameters (but rather use empty arrays). Perhaps assert that immutable arrays in various types are not default?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

correct. i will do that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

#resolved.

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@jcouv Have addressed all feedback.

Copy link
Copy Markdown
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

LGTM Thanks

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Apr 1, 2018

Don't forget to retarget the PR to feature branch.

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Apr 1, 2018

Also, any plans to implement adapt the Roslyn C# parser on top of VirtualChar so we can properly highlight embedded C#? ;-)

@CyrusNajmabadi CyrusNajmabadi changed the base branch from master to features/embeddedRegex April 1, 2018 22:10
@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@jcouv Have rebased to the new feature branch.

@dotnet/roslyn-ide could i get a quick pair of eyes on this small 300 line PR relating to the regex/json features?

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

Also, any plans to implement adapt the Roslyn C# parser on top of VirtualChar so we can properly highlight embedded C#? ;-)

Yes! Definitely. I also want ot make it work for the special strings we use for C# in our tests :)

Note: i don't think this will actually be difficult. I don't need to make the C# parser run on top fo virtual chars. I just need to feed it the .ValueText of the token. Then, any spans it passes back, i will map back myself using VirtualChar to the actual span.

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@jcouv If you feel pretty good aobut this one, we can merge in as well.

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Apr 2, 2018

I think PRs into feature branches follow the same process as other PRs, so they can be merged back into master without review of a massive PR.
@jmarolf @dotnet/roslyn-ide for a second review. Thanks

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

I think PRs into feature branches follow the same process as other PRs, so they can be merged back into master without review of a massive PR.
@jmarolf @dotnet/roslyn-ide for a second review. Thanks

Makes sense to me.

return TextSpan.FromBounds(start, end);
}

private void GetSpan(ref int start, ref int end)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like this could be a local function or this logic just get rolled up into GetSpan(). Is there a reason we want a separate private method here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

tried it out. Didn't think it helped. Plus, either you have the locals conflicting with the params, or hte local function mutates outer state. I didn't like either :)

Copy link
Copy Markdown
Contributor

@jmarolf jmarolf left a comment

Choose a reason for hiding this comment

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

:shipit:

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@jcouv or @jmarolf to merge in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants