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

Add in a json parser so that the IDE can provide services around json editing. #24110

Closed

Conversation

CyrusNajmabadi
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi commented Jan 8, 2018

Followup to #23984

So JFK has busted pipes. So i've been in airport limbo :-( On a good note, it gave me some time to expand on my previous Regex PR. Now, on top of Regex support in the IDE we also support JSON strings.

This also expands the previous interaction model with built in json detection for string tokens. i.e., if we see:

image

Then we'll offer:

image

This then helps users see how they can add a comment that lights-up IDE features for these types of strings. Note: i don't do this for regexes because of a concern about too many false positives. Once the comment is added things like up like so:

image

Of course, squiggles and braces are supported, on top of just colors:

image

Also, if you're using JToken/JObject/JArray, then you don't need to provide the comment (similar to how new Regex(pattern) is automatically detected:

image

Things to note:

  1. unlike regexes, this was much simpler to provide. That's because json is much simpler and much better documented versus the .net regex model.
  2. Two forms of json are supported. A strict mode that aligns with the IETF rfc for json, as well as Json.net's format. Json.net is clearly the .net json winner (almost 100m downloads) and is most likely what people will be using. Json.net allows a superset of standard json strings (including allowing things like comments, as well as other constructs that would normally be errors in es6 json).
  3. This leverages the VirtualChar work from the regex work, demonstrating that this is a suitable subsystem for general DSL plugins.

@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner January 8, 2018 22:04
@CyrusNajmabadi
Copy link
Member Author

Tagging @dotnet/roslyn-ide @Pilchie

@jasonmalinowski
Copy link
Member

@CyrusNajmabadi Should we wait until the regex one is resolved prior to looking at this one? This PR is quite, quite large.

@CyrusNajmabadi
Copy link
Member Author

Should we wait until the regex one is resolved prior to looking at this one?

That woudl be my recommendation :)

This PR is quite, quite large.

It's a mere 46k lines. If you do 2k lines an hour, you can finish it by tomorrow!

@sharwell sharwell added this to the 15.8 milestone Jan 8, 2018
@CyrusNajmabadi
Copy link
Member Author

Options look like this:

image

@yaakov-h
Copy link
Member

yaakov-h commented Jan 9, 2018

Can we just keep you in various airports? 😆

@CyrusNajmabadi
Copy link
Member Author

Tomorrow LaGuardia!

@CyrusNajmabadi
Copy link
Member Author

CyrusNajmabadi commented Mar 16, 2018

I have updated this PR to only be the json parser work. PR for IDE features around json strings has now moved into #25518

JSON parsing tests were pulled into: #25521

ImmutableArray<JsonTrivia> trailingTrivia, ImmutableArray<EmbeddedDiagnostic> diagnostics)
=> CreateToken(kind, leadingTrivia, virtualChars, trailingTrivia, diagnostics, value: null);

public static JsonToken CreateToken(JsonKind kind,
Copy link
Member

Choose a reason for hiding this comment

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

This method is only used once (on line 20). Inline?

Copy link
Member Author

Choose a reason for hiding this comment

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

done. #resolved.


internal static class JsonHelpers
{
public static JsonToken CreateToken(JsonKind kind, ImmutableArray<JsonTrivia> leadingTrivia, ImmutableArray<VirtualChar> virtualChars, ImmutableArray<JsonTrivia> trailingTrivia)
Copy link
Member

Choose a reason for hiding this comment

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

Nit: maybe break this line

Copy link
Member Author

Choose a reason for hiding this comment

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

done. #resolved.

@jcouv
Copy link
Member

jcouv commented Apr 3, 2018

Could you retarget to the feature branch?

{
internal enum JsonKind
{
None,
Copy link
Member

Choose a reason for hiding this comment

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

Is this used? If not, maybe None = 0 or remove?

Copy link
Member Author

Choose a reason for hiding this comment

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

i like this as it makes it easy to test if a token is default.

Copy link
Member

Choose a reason for hiding this comment

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

Should it be None = 0 then?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure. i can do that.

Copy link
Member Author

Choose a reason for hiding this comment

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

#resolved.

Text = text;
}

public VirtualChar CurrentChar => Position < Text.Length ? Text[Position] : new VirtualChar((char)0, default);
Copy link
Member

@jcouv jcouv Apr 3, 2018

Choose a reason for hiding this comment

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

Nit: name span: default?

Copy link
Member Author

Choose a reason for hiding this comment

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

done. #resolved.


public VirtualChar CurrentChar => Position < Text.Length ? Text[Position] : new VirtualChar((char)0, default);

public ImmutableArray<VirtualChar> GetSubPattern(int start, int end)
Copy link
Member

Choose a reason for hiding this comment

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

end is generally Position. Consider adding an overload where end is implicit.

Copy link
Member Author

Choose a reason for hiding this comment

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

done. #resolved.

case '\'': case '"':
return ScanString();

//case '-': case '.':
Copy link
Member

Choose a reason for hiding this comment

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

Why is this commented out?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added comment explaining why we do not explicitly lex out numbers here, but instead let the parser take control. #resolved.

private (ImmutableArray<VirtualChar>, JsonKind, EmbeddedDiagnostic?) ScanString()
{
var start = Position;
var startChar = this.CurrentChar.Char;
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps rename openChar?

Copy link
Member Author

Choose a reason for hiding this comment

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

done. #resolved.

return (chars, JsonKind.StringToken, diagnostic);
}

private EmbeddedDiagnostic? ScanEscape(int stringStart, int escapeStart)
Copy link
Member

Choose a reason for hiding this comment

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

ScanEscape could use a comment since unlike other scan methods, it doesn't return tokens or nodes, it just advances the position.

Copy link
Member Author

Choose a reason for hiding this comment

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

done. #Resolved

return (GetSubPattern(start, Position), JsonKind.TextToken, null);
}

private (ImmutableArray<VirtualChar>, JsonKind, EmbeddedDiagnostic?)? TryScanText(
Copy link
Member

Choose a reason for hiding this comment

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

This method seems unused

Copy link
Member Author

Choose a reason for hiding this comment

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

indeed. removed. #resolved.

var chars = GetSubPattern(start, Position);
if (Position == start + 2)
{
var diagnostics = ImmutableArray.Create(new EmbeddedDiagnostic(
Copy link
Member

Choose a reason for hiding this comment

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

What if // are the last two characters in the file?

Copy link
Member Author

Choose a reason for hiding this comment

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

then you get an unterminated comment diagnostic. This matches json.net. You can see a test for that here: https://github.com/dotnet/roslyn/pull/25521/files#diff-d0475d1c64e0a4bb26665ae88ff3cf24R158

Will add a comment explaining this is intentional.

Copy link
Member Author

Choose a reason for hiding this comment

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

added comment. #resolved.

GetTextSpan(start, Position))));
}

public TextSpan GetTextSpan(int startInclusive, int endExclusive)
Copy link
Member

Choose a reason for hiding this comment

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

This method seems to only be used once. private?

Copy link
Member Author

Choose a reason for hiding this comment

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

made privat.e #resolved

@CyrusNajmabadi
Copy link
Member Author

@sharwell @jinujoseph How would you like to proceed on this?

1 similar comment
@CyrusNajmabadi
Copy link
Member Author

@sharwell @jinujoseph How would you like to proceed on this?

@jinujoseph
Copy link
Contributor

Unfortunately, This feature is currently not in the top priority for us to pursue, so this is on hold at this moment. Following up to see if we can get merge this to feature branch

@sharwell sharwell removed their assignment Oct 17, 2018
@jinujoseph
Copy link
Contributor

@CyrusNajmabadi as discussed closing this PR for now.

@jinujoseph jinujoseph closed this Nov 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE Community The pull request was submitted by a contributor who is not a Microsoft employee.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants