提交 40f54274 编写于 作者: C Cyrus Najmabadi

Add json constructors.

上级 eb7dd029
......@@ -633,6 +633,22 @@ private JsonPropertyNameFormatDefinition()
this.ForegroundColor = Color.FromRgb(202, 121, 236);
}
}
[Export(typeof(EditorFormatDefinition))]
[ClassificationType(ClassificationTypeNames = ClassificationTypeNames.JsonConstructorName)]
[Name(ClassificationTypeNames.JsonConstructorName)]
[Order(After = ClassificationTypeNames.StringLiteral)]
[Order(After = ClassificationTypeNames.VerbatimStringLiteral)]
[UserVisible(true)]
[ExcludeFromCodeCoverage]
private class JsonConstructorNameFormatDefinition : ClassificationFormatDefinition
{
private JsonConstructorNameFormatDefinition()
{
this.DisplayName = EditorFeaturesWpfResources.JSON_Constructor_Name;
this.ForegroundColor = Color.FromRgb(78, 201, 176);
}
}
#endregion
......
......@@ -105,6 +105,15 @@ internal class EditorFeaturesWpfResources {
}
}
/// <summary>
/// Looks up a localized string similar to JSON Constructor Name.
/// </summary>
internal static string JSON_Constructor_Name {
get {
return ResourceManager.GetString("JSON_Constructor_Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to JSON Keyword.
/// </summary>
......
......@@ -180,4 +180,7 @@
<data name="JSON_Text" xml:space="preserve">
<value>JSON Text</value>
</data>
<data name="JSON_Constructor_Name" xml:space="preserve">
<value>JSON Constructor Name</value>
</data>
</root>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -107,6 +107,11 @@
<target state="new">JSON Punctuation</target>
<note />
</trans-unit>
<trans-unit id="JSON_Constructor_Name">
<source>JSON Constructor Name</source>
<target state="new">JSON Constructor Name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -226,6 +226,11 @@ internal sealed class ClassificationTypeDefinitions
[Name(ClassificationTypeNames.JsonPropertyName)]
[BaseDefinition(PredefinedClassificationTypeNames.FormalLanguage)]
internal readonly ClassificationTypeDefinition JsonPropertyNameTypeDefinition;
[Export]
[Name(ClassificationTypeNames.JsonConstructorName)]
[BaseDefinition(PredefinedClassificationTypeNames.FormalLanguage)]
internal readonly ClassificationTypeDefinition JsonConstructorNameTypeDefinition;
#endregion
#region VB XML Literals - Attribute Name
......
......@@ -93,6 +93,7 @@ public void RefreshThemeColors()
UpdateForegroundColor(ClassificationTypeNames.JsonArray, sourceFormatMap, targetFormatMap);
UpdateForegroundColor(ClassificationTypeNames.JsonObject, sourceFormatMap, targetFormatMap);
UpdateForegroundColor(ClassificationTypeNames.JsonPropertyName, sourceFormatMap, targetFormatMap);
UpdateForegroundColor(ClassificationTypeNames.JsonConstructorName, sourceFormatMap, targetFormatMap);
UpdateForegroundColor(ClassificationTypeNames.PreprocessorKeyword, sourceFormatMap, targetFormatMap);
UpdateForegroundColor(ClassificationTypeNames.PreprocessorText, sourceFormatMap, targetFormatMap);
......
......@@ -28,7 +28,7 @@ protected override ImmutableArray<VirtualChar> TryConvertToVirtualCharsWorker(Sy
}
private ImmutableArray<VirtualChar> TryConvertVerbatimStringToVirtualChars(SyntaxToken token)
=> TryConvertSimpleDelimitedString(token, "@\"", "\"");
=> TryConvertSimpleDoubleQuoteString(token, "@\"", "\"");
private ImmutableArray<VirtualChar> TryConvertStringToVirtualChars(SyntaxToken token)
{
......
......@@ -1434,13 +1434,47 @@ public void TestStrangeLegalPropName()
public void TestStrangeIllegalPropName()
{
Test(@"@""{ 0(0 : 0 }""", @"<Tree>
<CompilationUnit>
<Sequence>
<Object>
<OpenBraceToken>{<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></OpenBraceToken>
<Sequence>
<Literal>
<NumberToken>0</NumberToken>
</Literal>
<Text>
<TextToken>(</TextToken>
</Text>
<Property>
<TextToken>0<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></TextToken>
<ColonToken>:<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></ColonToken>
<Literal>
<NumberToken>0<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NumberToken>
</Literal>
</Property>
</Sequence>
<CloseBraceToken>}</CloseBraceToken>
</Object>
</Sequence>
<EndOfFile />
</CompilationUnit>
<Diagnostics>
<Diagnostic Message=""'(' unexpected"" Start=""13"" Length=""1"" />
</Diagnostics>
</Tree>");
}
[Fact]
public void TestStrangeIllegalPropName2()
{
Test(@"@""{ 0%0 : 0 }""", @"<Tree>
<CompilationUnit>
<Sequence>
<Object>
<OpenBraceToken>{<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></OpenBraceToken>
<Sequence>
<Property>
<TextToken>0(0<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></TextToken>
<TextToken>0%0<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></TextToken>
<ColonToken>:<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></ColonToken>
<Literal>
<NumberToken>0<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NumberToken>
......@@ -2426,6 +2460,404 @@ public void TestMultiLineString()
</Sequence>
<EndOfFile />
</CompilationUnit>
</Tree>");
}
[Fact]
public void TestConstructor1()
{
Test(@"@""new""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new</NewKeyword>
<TextToken />
<OpenParenToken />
<Sequence />
<CloseParenToken />
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
<Diagnostics>
<Diagnostic Message=""Name expected"" Start=""13"" Length=""0"" />
</Diagnostics>
</Tree>");
}
[Fact]
public void TestConstructor2()
{
Test(@"@""new A""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken />
<Sequence />
<CloseParenToken />
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
<Diagnostics>
<Diagnostic Message=""'(' expected"" Start=""15"" Length=""0"" />
</Diagnostics>
</Tree>");
}
[Fact]
public void TestConstructor3()
{
Test(@"@""new A(""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence />
<CloseParenToken />
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
<Diagnostics>
<Diagnostic Message=""')' expected"" Start=""16"" Length=""0"" />
</Diagnostics>
</Tree>");
}
[Fact]
public void TestConstructor4()
{
Test(@"@""new A()""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence />
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
</Tree>");
}
[Fact]
public void TestConstructor5()
{
Test(@"@""new A(1)""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence>
<Literal>
<NumberToken>1</NumberToken>
</Literal>
</Sequence>
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
</Tree>");
}
[Fact]
public void TestConstructor6()
{
Test(@"@""new A(1, 2)""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence>
<Literal>
<NumberToken>1</NumberToken>
</Literal>
<EmptyValue>
<CommaToken>,<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></CommaToken>
</EmptyValue>
<Literal>
<NumberToken>2</NumberToken>
</Literal>
</Sequence>
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
</Tree>");
}
[Fact]
public void TestConstructor7()
{
Test(@"@""new A([new B()])""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence>
<Array>
<OpenBracketToken>[</OpenBracketToken>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>B</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence />
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<CloseBracketToken>]</CloseBracketToken>
</Array>
</Sequence>
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
</Tree>");
}
[Fact]
public void TestConstructor8()
{
Test(@"@""new A(,)""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence>
<EmptyValue>
<CommaToken>,</CommaToken>
</EmptyValue>
</Sequence>
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
</Tree>");
}
[Fact]
public void TestConstructor9()
{
Test(@"@""new A(1,)""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence>
<Literal>
<NumberToken>1</NumberToken>
</Literal>
<EmptyValue>
<CommaToken>,</CommaToken>
</EmptyValue>
</Sequence>
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
</Tree>");
}
[Fact]
public void TestConstructor10()
{
Test(@"@""new A(,1)""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence>
<EmptyValue>
<CommaToken>,</CommaToken>
</EmptyValue>
<Literal>
<NumberToken>1</NumberToken>
</Literal>
</Sequence>
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
</Tree>");
}
[Fact]
public void TestConstructor11()
{
Test(@"@""new A(1,1)""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence>
<Literal>
<NumberToken>1</NumberToken>
</Literal>
<EmptyValue>
<CommaToken>,</CommaToken>
</EmptyValue>
<Literal>
<NumberToken>1</NumberToken>
</Literal>
</Sequence>
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
</Tree>");
}
[Fact]
public void TestConstructor12()
{
Test(@"@""new A(1,,1)""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence>
<Literal>
<NumberToken>1</NumberToken>
</Literal>
<EmptyValue>
<CommaToken>,</CommaToken>
</EmptyValue>
<EmptyValue>
<CommaToken>,</CommaToken>
</EmptyValue>
<Literal>
<NumberToken>1</NumberToken>
</Literal>
</Sequence>
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
</Tree>");
}
[Fact]
public void TestConstructor13()
{
Test(@"@""new %()""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>%</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence />
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
<Diagnostics>
<Diagnostic Message=""Invalid constructor name"" Start=""14"" Length=""1"" />
</Diagnostics>
</Tree>");
}
[Fact]
public void TestConstructor14()
{
Test(@"@""new A(1 2)""", @"<Tree>
<CompilationUnit>
<Sequence>
<Constructor>
<NewKeyword>new<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NewKeyword>
<TextToken>A</TextToken>
<OpenParenToken>(</OpenParenToken>
<Sequence>
<Literal>
<NumberToken>1<Trivia><WhitespaceTrivia> </WhitespaceTrivia></Trivia></NumberToken>
</Literal>
<Literal>
<NumberToken>2</NumberToken>
</Literal>
</Sequence>
<CloseParenToken>)</CloseParenToken>
</Constructor>
</Sequence>
<EndOfFile />
</CompilationUnit>
<Diagnostics>
<Diagnostic Message=""',' expected"" Start=""18"" Length=""1"" />
</Diagnostics>
</Tree>");
}
[Fact]
public void TestMultipleCommasInObject()
{
Test(@"@""{0:0,,1:1}""", @"<Tree>
<CompilationUnit>
<Sequence>
<Object>
<OpenBraceToken>{</OpenBraceToken>
<Sequence>
<Property>
<TextToken>0</TextToken>
<ColonToken>:</ColonToken>
<Literal>
<NumberToken>0</NumberToken>
</Literal>
</Property>
<EmptyValue>
<CommaToken>,</CommaToken>
</EmptyValue>
<EmptyValue>
<CommaToken>,</CommaToken>
</EmptyValue>
<Property>
<TextToken>1</TextToken>
<ColonToken>:</ColonToken>
<Literal>
<NumberToken>1</NumberToken>
</Literal>
</Property>
</Sequence>
<CloseBraceToken>}</CloseBraceToken>
</Object>
</Sequence>
<EndOfFile />
</CompilationUnit>
<Diagnostics>
<Diagnostic Message=""Only properties allowed in a json object"" Start=""15"" Length=""1"" />
</Diagnostics>
</Tree>");
}
}
......
......@@ -69,5 +69,6 @@ public static class ClassificationTypeNames
internal const string JsonArray = "json - array";
internal const string JsonObject = "json - object";
internal const string JsonPropertyName = "json - property name";
internal const string JsonConstructorName = "json - constructor name";
}
}
......@@ -153,6 +153,14 @@ public void Visit(JsonPropertyNode node)
AddClassification(node.ColonToken, ClassificationTypeNames.JsonPunctuation);
}
public void Visit(JsonConstructorNode node)
{
AddClassification(node.NewKeyword, ClassificationTypeNames.JsonKeyword);
AddClassification(node.NameToken, ClassificationTypeNames.JsonConstructorName);
AddClassification(node.OpenParenToken, ClassificationTypeNames.JsonPunctuation);
AddClassification(node.CloseParenToken, ClassificationTypeNames.JsonPunctuation);
}
public void Visit(JsonLiteralNode node)
{
VisitLiteral(node.LiteralToken);
......
......@@ -10,6 +10,7 @@ internal interface IJsonNodeVisitor
void Visit(JsonArrayNode node);
void Visit(JsonObjectNode node);
void Visit(JsonPropertyNode node);
void Visit(JsonConstructorNode node);
void Visit(JsonLiteralNode node);
void Visit(JsonNegativeLiteralNode node);
void Visit(JsonTextNode node);
......
......@@ -13,6 +13,7 @@ internal enum JsonKind
Literal,
NegativeLiteral,
Property,
Constructor,
EmptyValue,
// Tokens
......@@ -21,6 +22,8 @@ internal enum JsonKind
CloseBraceToken,
OpenBracketToken,
CloseBracketToken,
OpenParenToken,
CloseParenToken,
StringToken,
NumberToken,
TextToken,
......@@ -34,6 +37,7 @@ internal enum JsonKind
InfinityLiteralToken,
NegativeInfinityLiteralToken,
MinusToken,
NewKeyword,
// Trivia
SingleLineCommentTrivia,
......
......@@ -66,8 +66,9 @@ private bool IsSpecial(char ch)
{
case '{': case '}':
case '[': case ']':
case '(': case ')':
case ',': case ':':
case '\'': case '"':
case '\'': case '"':
return true;
case ' ': case '\t': case '/': case '\r': case '\n':
......@@ -93,6 +94,8 @@ private bool IsSpecial(char ch)
case '}': return ScanSingleCharToken(JsonKind.CloseBraceToken);
case '[': return ScanSingleCharToken(JsonKind.OpenBracketToken);
case ']': return ScanSingleCharToken(JsonKind.CloseBracketToken);
case '(': return ScanSingleCharToken(JsonKind.OpenParenToken);
case ')': return ScanSingleCharToken(JsonKind.CloseParenToken);
case ',': return ScanSingleCharToken(JsonKind.CommaToken);
case ':': return ScanSingleCharToken(JsonKind.ColonToken);
......
......@@ -296,4 +296,43 @@ public override JsonNodeOrToken ChildAt(int index)
public override void Accept(IJsonNodeVisitor visitor)
=> visitor.Visit(this);
}
internal sealed class JsonConstructorNode : JsonValueNode
{
public JsonConstructorNode(
JsonToken newKeyword, JsonToken nameToken, JsonToken openParenToken, JsonSequenceNode sequence, JsonToken closeParenToken)
: base(JsonKind.Constructor)
{
NewKeyword = newKeyword;
NameToken = nameToken;
OpenParenToken = openParenToken;
Sequence = sequence;
CloseParenToken = closeParenToken;
}
public JsonToken NewKeyword { get; }
public JsonToken NameToken { get; }
public JsonToken OpenParenToken { get; }
public JsonSequenceNode Sequence { get; }
public JsonToken CloseParenToken { get; }
public override int ChildCount => 5;
public override JsonNodeOrToken ChildAt(int index)
{
switch (index)
{
case 0: return NewKeyword;
case 1: return NameToken;
case 2: return OpenParenToken;
case 3: return Sequence;
case 4: return CloseParenToken;
}
throw new InvalidOperationException();
}
public override void Accept(IJsonNodeVisitor visitor)
=> visitor.Visit(this);
}
}
......@@ -18,12 +18,15 @@ internal partial struct JsonParser
{
private static readonly string _closeBracketExpected = string.Format(WorkspacesResources._0_expected, ']');
private static readonly string _closeBraceExpected = string.Format(WorkspacesResources._0_expected, '}');
private static readonly string _openParenExpected = string.Format(WorkspacesResources._0_expected, '(');
private static readonly string _closeParenExpected = string.Format(WorkspacesResources._0_expected, ')');
private JsonLexer _lexer;
private JsonToken _currentToken;
private int _recursionDepth;
private bool _inObject;
private bool _inArray;
private bool _inConstructor;
private JsonParser(
ImmutableArray<VirtualChar> text) : this()
......@@ -206,6 +209,16 @@ private JsonToken GetFirstToken(JsonNode node)
}
}
break;
case JsonKind.Constructor:
{
var diagnostic = CheckConstructor((JsonConstructorNode)node);
if (diagnostic != null)
{
return diagnostic;
}
}
break;
}
foreach (var child in node)
......@@ -236,13 +249,20 @@ private JsonToken GetFirstToken(JsonNode node)
}
}
return CheckCommasBetweenSequenceElements(node.Sequence);
}
for (int i = 0, n = node.Sequence.ChildCount - 1; i < n; i++)
private JsonDiagnostic? CheckConstructor(JsonConstructorNode node)
=> CheckCommasBetweenSequenceElements(node.Sequence);
private JsonDiagnostic? CheckCommasBetweenSequenceElements(JsonSequenceNode node)
{
for (int i = 0, n = node.ChildCount - 1; i < n; i++)
{
var child = node.Sequence.ChildAt(i).Node;
var child = node.ChildAt(i).Node;
if (child.Kind != JsonKind.EmptyValue)
{
var next = node.Sequence.ChildAt(i + 1).Node;
var next = node.ChildAt(i + 1).Node;
if (next.Kind != JsonKind.EmptyValue)
{
......@@ -332,6 +352,11 @@ private bool ShouldConsumeSequenceElement()
return !_inArray;
}
if (_currentToken.Kind == JsonKind.CloseParenToken)
{
return !_inConstructor;
}
return true;
}
......@@ -346,7 +371,7 @@ private JsonValueNode ParseValue()
case JsonKind.CommaToken:
return ParseEmptyValue();
default:
return ParseLiteralOrProperty();
return ParseLiteralOrPropertyOrConstructor();
}
}
......@@ -427,25 +452,30 @@ private bool IsLegalPropertyNameText(JsonToken textToken)
private bool IsLegalPropertyNameChar(char ch)
=> char.IsLetterOrDigit(ch) | ch == '_' || ch == '$';
private JsonValueNode ParseLiteralOrProperty()
private JsonValueNode ParseLiteralOrPropertyOrConstructor()
{
// var token = ConsumeCurrentToken().With(kind: JsonKind.TextToken);
var textToken = ConsumeCurrentToken();
if (_currentToken.Kind != JsonKind.ColonToken)
{
return ParseLiteralOrTextNode(textToken);
return ParseLiteralOrTextOrConstructor(textToken);
}
return ParseProperty(textToken);
}
private JsonValueNode ParseLiteralOrTextNode(JsonToken token)
private JsonValueNode ParseLiteralOrTextOrConstructor(JsonToken token)
{
if (token.Kind == JsonKind.StringToken)
{
return new JsonLiteralNode(token);
}
if (Matches(token, "new"))
{
return ParseConstructor(token);
}
Debug.Assert(token.VirtualChars.Length > 0);
if (TryMatch(token, "NaN", JsonKind.NaNLiteralToken, out var newKind) ||
TryMatch(token, "true", JsonKind.TrueLiteralToken, out newKind) ||
......@@ -477,6 +507,47 @@ private JsonValueNode ParseLiteralOrTextNode(JsonToken token)
firstChar.Span)));
}
private JsonConstructorNode ParseConstructor(JsonToken token)
{
var newKeyword = token.With(kind: JsonKind.NewKeyword);
var nameToken = ConsumeToken(JsonKind.TextToken, WorkspacesResources.Name_expected);
if (!IsValidConstructorName(nameToken))
{
nameToken = nameToken.AddDiagnosticIfNone(new JsonDiagnostic(
WorkspacesResources.Invalid_constructor_name,
GetSpan(nameToken)));
}
var openParen = ConsumeToken(JsonKind.OpenParenToken, _openParenExpected);
var savedInConstructor = _inConstructor;
_inConstructor = true;
var result = new JsonConstructorNode(
newKeyword,
nameToken,
openParen,
ParseSequence(),
ConsumeToken(JsonKind.CloseParenToken, _closeParenExpected));
_inConstructor = savedInConstructor;
return result;
}
private bool IsValidConstructorName(JsonToken nameToken)
{
foreach (var vc in nameToken.VirtualChars)
{
if (!char.IsLetterOrDigit(vc.Char))
{
return false;
}
}
return true;
}
private bool TryMatch(JsonToken token, string val, JsonKind kind, out JsonKind newKind)
{
if (Matches(token, val))
......@@ -583,7 +654,7 @@ private JsonArrayNode ParseArray()
var result = new JsonArrayNode(
ConsumeCurrentToken(),
ParseSequence(),
ParseClose(JsonKind.CloseBracketToken, _closeBracketExpected));
ConsumeToken(JsonKind.CloseBracketToken, _closeBracketExpected));
_inArray = savedInArray;
return result;
......@@ -597,20 +668,13 @@ private JsonObjectNode ParseObject()
var result = new JsonObjectNode(
ConsumeCurrentToken(),
ParseSequence(),
ParseClose(JsonKind.CloseBraceToken, _closeBraceExpected));
ConsumeToken(JsonKind.CloseBraceToken, _closeBraceExpected));
_inObject = savedInObject;
return result;
}
//private JsonToken ConsumeOptionalCommaToken()
//{
// return _currentToken.Kind == JsonKind.CommaToken
// ? ConsumeCurrentToken()
// : JsonToken.CreateMissing(JsonKind.CommaToken);
//}
private JsonToken ParseClose(JsonKind kind, string error)
private JsonToken ConsumeToken(JsonKind kind, string error)
{
if (_currentToken.Kind == kind)
{
......
......@@ -881,6 +881,15 @@ internal class WorkspacesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Invalid constructor name.
/// </summary>
internal static string Invalid_constructor_name {
get {
return ResourceManager.GetString("Invalid_constructor_name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid escape sequence.
/// </summary>
......@@ -1115,6 +1124,15 @@ internal class WorkspacesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Name expected.
/// </summary>
internal static string Name_expected {
get {
return ResourceManager.GetString("Name_expected", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Nested properties not allowed.
/// </summary>
......
......@@ -745,4 +745,10 @@
<data name="Nested_properties_not_allowed" xml:space="preserve">
<value>Nested properties not allowed</value>
</data>
<data name="Name_expected" xml:space="preserve">
<value>Name expected</value>
</data>
<data name="Invalid_constructor_name" xml:space="preserve">
<value>Invalid constructor name</value>
</data>
</root>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1017,6 +1017,16 @@
<target state="new">Nested properties not allowed</target>
<note />
</trans-unit>
<trans-unit id="Name_expected">
<source>Name expected</source>
<target state="new">Name expected</target>
<note />
</trans-unit>
<trans-unit id="Invalid_constructor_name">
<source>Invalid constructor name</source>
<target state="new">Invalid constructor name</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -13,7 +13,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VirtualChars
Public Shared ReadOnly Instance As IVirtualCharService = New VisualBasicVirtualCharService()
Protected Overrides Function TryConvertToVirtualCharsWorker(token As SyntaxToken) As ImmutableArray(Of VirtualChar)
Return TryConvertSimpleDelimitedString(token, """", """")
Return TryConvertSimpleDoubleQuoteString(token, """", """")
End Function
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册