提交 09a6933f 编写于 作者: A Andrew Casey 提交者: Artur Spychaj

This is a partial fix for #3819 - #r in VB

I've done some manual testing, but there are no unit tests.

Existing unit tests are pass, except for ParseXml.Bug674567.  The fix is
either to change the baseline or to merge
https://github.com/dotnet/roslyn/pull/3957.

Conflicts:
	src/Compilers/VisualBasic/Portable/Scanner/Scanner.vb
	src/Compilers/VisualBasic/Portable/Syntax/CompilationUnitSyntax.vb
	src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb
上级 db627099
......@@ -149,13 +149,12 @@ private static ImmutableArray<ReferenceDirective> GetReferenceDirectives(Compila
return ImmutableArray<ReferenceDirective>.Empty;
}
var directives = new ReferenceDirective[directiveNodes.Count];
for (int i = 0; i < directives.Length; i++)
var directives = ArrayBuilder<ReferenceDirective>.GetInstance(directiveNodes.Count);
foreach (var directiveNode in directiveNodes)
{
directives[i] = new ReferenceDirective(directiveNodes[i].File.ValueText, new SourceLocation(directiveNodes[i]));
directives.Add(new ReferenceDirective(directiveNode.File.ValueText, new SourceLocation(directiveNode)));
}
return directives.AsImmutableOrNull();
return directives.ToImmutableAndFree();
}
private SingleNamespaceOrTypeDeclaration CreateScriptClass(
......
......@@ -91,20 +91,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return children
End Function
Private Function GetReferenceDirectives(compilationUnit As CompilationUnitSyntax) As ImmutableArray(Of ReferenceDirective)
Dim directiveNodes = compilationUnit.GetReferenceDirectives(Function(d) Not d.File.ContainsDiagnostics AndAlso Not String.IsNullOrEmpty(d.File.ValueText))
Private Shared Function GetReferenceDirectives(compilationUnit As CompilationUnitSyntax) As ImmutableArray(Of ReferenceDirective)
Dim directiveNodes = compilationUnit.GetReferenceDirectives(
Function(d) Not d.File.ContainsDiagnostics AndAlso Not String.IsNullOrEmpty(d.File.ValueText))
If directiveNodes.Count = 0 Then
Return ImmutableArray(Of ReferenceDirective).Empty
End If
Dim directives = New ReferenceDirective(directiveNodes.Count - 1) {}
For i = 0 To directives.Length - 1
directives(i) = New ReferenceDirective(directiveNodes(i).File.ValueText, directiveNodes(i).GetLocation())
Dim directives = ArrayBuilder(Of ReferenceDirective).GetInstance(directiveNodes.Count)
For Each directiveNode In directiveNodes
directives.Add(New ReferenceDirective(directiveNode.File.ValueText, New SourceLocation(directiveNode)))
Next
Return directives.AsImmutableOrNull()
Return directives.ToImmutableAndFree()
End Function
Private Function CreateImplicitClass(parent As VisualBasicSyntaxNode, memberNames As String(), children As ImmutableArray(Of SingleTypeDeclaration), declFlags As SingleTypeDeclaration.TypeDeclarationFlags) As SingleNamespaceOrTypeDeclaration
......@@ -162,6 +160,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Dim syntaxRef = _syntaxTree.GetReference(node)
Dim implicitClass As SingleNamespaceOrTypeDeclaration = Nothing
Dim referenceDirectives As ImmutableArray(Of ReferenceDirective)
If _syntaxTree.Options.Kind <> SourceCodeKind.Regular Then
Dim childrenBuilder = ArrayBuilder(Of SingleNamespaceOrTypeDeclaration).GetInstance()
Dim scriptChildren = ArrayBuilder(Of SingleTypeDeclaration).GetInstance()
......@@ -185,8 +184,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
implicitClass = CreateScriptClass(node, scriptChildren.ToImmutableAndFree(), memberNames, declFlags)
children = childrenBuilder.ToImmutableAndFree()
referenceDirectives = GetReferenceDirectives(node)
Else
children = VisitNamespaceChildren(node, node.Members, implicitClass).ToImmutableAndFree()
referenceDirectives = ImmutableArray(Of ReferenceDirective).Empty
End If
' Find children within NamespaceGlobal separately
......@@ -198,7 +199,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
hasImports:=True,
treeNode:=_syntaxTree.GetReference(node),
children:=globalChildren.Concat(nonGlobal),
referenceDirectives:=ImmutableArray(Of ReferenceDirective).Empty,
referenceDirectives:=referenceDirectives,
hasAssemblyAttributes:=node.Attributes.Any)
Else
' Project-level root namespace. All children without explicit global are children
......@@ -213,7 +214,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
hasImports:=True,
treeNode:=_syntaxTree.GetReference(node),
children:=newChildren,
referenceDirectives:=ImmutableArray(Of ReferenceDirective).Empty,
referenceDirectives:=referenceDirectives,
hasAssemblyAttributes:=node.Attributes.Any)
End If
End Function
......
......@@ -76,6 +76,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Case SyntaxKind.EnableKeyword, SyntaxKind.DisableKeyword
statement = ParseWarningDirective(hashToken)
Case SyntaxKind.ReferenceKeyword
statement = ParseReferenceDirective(hashToken)
Case Else
statement = ParseBadDirective(hashToken)
End Select
......@@ -248,7 +251,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Private Function ParseRegionDirective(hashToken As PunctuationSyntax) As RegionDirectiveTriviaSyntax
Debug.Assert(CurrentToken.Kind = SyntaxKind.IdentifierToken AndAlso DirectCast(CurrentToken, IdentifierTokenSyntax).PossibleKeywordKind = SyntaxKind.RegionKeyword,
"ParseRegionDirective called with wrong token.")
$"{NameOf(ParseRegionDirective)} called with wrong token.")
Dim identifier = DirectCast(CurrentToken, IdentifierTokenSyntax)
GetNextToken()
......@@ -262,7 +265,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Private Function ParseExternalSourceDirective(hashToken As PunctuationSyntax) As ExternalSourceDirectiveTriviaSyntax
Debug.Assert(CurrentToken.Kind = SyntaxKind.IdentifierToken AndAlso DirectCast(CurrentToken, IdentifierTokenSyntax).PossibleKeywordKind = SyntaxKind.ExternalSourceKeyword,
"ParseExternalSourceDirective called with wrong token")
$"{NameOf(ParseExternalSourceDirective)} called with wrong token")
Dim identifier = DirectCast(CurrentToken, IdentifierTokenSyntax)
Dim externalSourceKeyword = _scanner.MakeKeyword(identifier)
......@@ -309,7 +312,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Private Function ParseExternalChecksumDirective(hashToken As PunctuationSyntax) As ExternalChecksumDirectiveTriviaSyntax
Debug.Assert(CurrentToken.Kind = SyntaxKind.IdentifierToken AndAlso DirectCast(CurrentToken, IdentifierTokenSyntax).PossibleKeywordKind = SyntaxKind.ExternalChecksumKeyword,
"ParseExternalChecksumDirective called with wrong token")
$"{NameOf(ParseExternalChecksumDirective)} called with wrong token")
Dim identifier = DirectCast(CurrentToken, IdentifierTokenSyntax)
Dim externalChecksumKeyword = _scanner.MakeKeyword(identifier)
......@@ -377,12 +380,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Private Function ParseWarningDirective(hashToken As PunctuationSyntax) As DirectiveTriviaSyntax
Debug.Assert(CurrentToken.Kind = SyntaxKind.IdentifierToken,
"ParseWarningDirective called with token that is not an IdentifierToken")
$"{NameOf(ParseWarningDirective)} called with token that is not an {NameOf(SyntaxKind.IdentifierToken)}")
Dim identifier = DirectCast(CurrentToken, IdentifierTokenSyntax)
Debug.Assert((identifier.PossibleKeywordKind = SyntaxKind.EnableKeyword) OrElse
(identifier.PossibleKeywordKind = SyntaxKind.DisableKeyword),
"ParseWarningDirective called with token that is neither EnableKeyword nor DisableKeyword")
$"{NameOf(ParseWarningDirective)} called with token that is neither {NameOf(SyntaxKind.EnableKeyword)} nor {NameOf(SyntaxKind.DisableKeyword)}")
Dim enableOrDisableKeyword = _scanner.MakeKeyword(identifier)
GetNextToken()
......@@ -439,6 +442,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Return statement
End Function
Private Function ParseReferenceDirective(hashToken As PunctuationSyntax) As DirectiveTriviaSyntax
Debug.Assert(CurrentToken.Kind = SyntaxKind.IdentifierToken AndAlso DirectCast(CurrentToken, IdentifierTokenSyntax).PossibleKeywordKind = SyntaxKind.ReferenceKeyword,
$"{NameOf(ParseReferenceDirective)} called with wrong token.")
Dim identifier = DirectCast(CurrentToken, IdentifierTokenSyntax)
GetNextToken()
Dim referenceKeyword = _scanner.MakeKeyword(identifier)
If Not IsScript Then
referenceKeyword = AddError(referenceKeyword, ERRID.ERR_ReferenceDirectiveOnlyAllowedInScripts)
End If
Dim title As StringLiteralTokenSyntax = Nothing
VerifyExpectedToken(SyntaxKind.StringLiteralToken, title)
Return SyntaxFactory.ReferenceDirectiveTrivia(hashToken, referenceKeyword, title)
End Function
Private Shared Function ParseBadDirective(hashToken As PunctuationSyntax) As BadDirectiveTriviaSyntax
Dim badDirective = InternalSyntaxFactory.BadDirectiveTrivia(hashToken)
......
......@@ -208,7 +208,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Case SyntaxKind.ExternalChecksumDirectiveTrivia,
SyntaxKind.BadDirectiveTrivia,
SyntaxKind.EnableWarningDirectiveTrivia, 'TODO: Add support for processing #Enable and #Disable
SyntaxKind.DisableWarningDirectiveTrivia
SyntaxKind.DisableWarningDirectiveTrivia,
SyntaxKind.ReferenceDirectiveTrivia
' These directives require no processing
......
......@@ -131,6 +131,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax
SyntaxKind.PublicKeyword, None,
SyntaxKind.RaiseEventKeyword, None,
SyntaxKind.ReadOnlyKeyword, None,
SyntaxKind.ReferenceKeyword, None,
SyntaxKind.ReDimKeyword, None,
SyntaxKind.REMKeyword, CanFollowExpr,
SyntaxKind.RemoveHandlerKeyword, None,
......@@ -297,7 +298,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax
Dim kind As SyntaxKind
If Not s_keywords.TryGetValue(tokenName, kind) Then
kind = SyntaxKind.IdentifierToken
' s_keywords includes preprocessor keywords, but only one of
' "r" and "reference". GetProcessorKeywordKind supports both.
Dim preprocessorKind = SyntaxFacts.GetPreprocessorKeywordKind(tokenName)
Debug.Assert(preprocessorKind = SyntaxKind.None OrElse preprocessorKind = SyntaxKind.ReferenceKeyword)
kind = If(preprocessorKind <> SyntaxKind.None, preprocessorKind, SyntaxKind.IdentifierToken)
End If
Return kind
End Function
......
......@@ -1469,7 +1469,7 @@ FullWidthRepeat:
End Function
Private Function TokenOfStringCached(spelling As String) As SyntaxKind
If spelling.Length = 1 OrElse spelling.Length > 16 Then
If spelling.Length > 16 Then
Return SyntaxKind.IdentifierToken
End If
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System
Imports System.Collections.Generic
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax
Partial Public NotInheritable Class CompilationUnitSyntax
......
......@@ -342,6 +342,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
SyntaxKind.OrderKeyword,
SyntaxKind.PreserveKeyword,
SyntaxKind.RegionKeyword,
SyntaxKind.ReferenceKeyword,
SyntaxKind.SkipKeyword,
SyntaxKind.StrictKeyword,
SyntaxKind.TextKeyword,
......
......@@ -18,9 +18,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' Determine if the kind represents a contextual keyword
''' </summary>
Public Shared Function IsContextualKeyword(kind As SyntaxKind) As Boolean
Return kind - SyntaxKind.AggregateKeyword <=
SyntaxKind.YieldKeyword - SyntaxKind.AggregateKeyword
Return kind = SyntaxKind.ReferenceKeyword OrElse
(SyntaxKind.AggregateKeyword <= kind AndAlso kind <= SyntaxKind.YieldKeyword)
End Function
''' <summary>
......@@ -66,6 +65,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
SyntaxKind.RegionKeyword,
SyntaxKind.EndKeyword,
SyntaxKind.ConstKeyword,
SyntaxKind.ReferenceKeyword,
SyntaxKind.EnableKeyword,
SyntaxKind.DisableKeyword,
SyntaxKind.ExternalSourceKeyword,
......@@ -272,6 +272,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
SyntaxKind.OutKeyword,
SyntaxKind.PreserveKeyword,
SyntaxKind.RegionKeyword,
SyntaxKind.ReferenceKeyword,
SyntaxKind.SkipKeyword,
SyntaxKind.StrictKeyword,
SyntaxKind.TakeKeyword,
......@@ -354,6 +355,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
SyntaxKind.EndKeyword,
SyntaxKind.RegionKeyword,
SyntaxKind.ConstKeyword,
SyntaxKind.ReferenceKeyword,
SyntaxKind.EnableKeyword,
SyntaxKind.DisableKeyword,
SyntaxKind.WarningKeyword,
......@@ -797,6 +799,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
{"out", SyntaxKind.OutKeyword},
{"preserve", SyntaxKind.PreserveKeyword},
{"region", SyntaxKind.RegionKeyword},
{"reference", SyntaxKind.ReferenceKeyword},
{"r", SyntaxKind.ReferenceKeyword},
{"skip", SyntaxKind.SkipKeyword},
{"strict", SyntaxKind.StrictKeyword},
{"take", SyntaxKind.TakeKeyword},
......@@ -831,6 +835,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
{"const", SyntaxKind.ConstKeyword},
{"externalsource", SyntaxKind.ExternalSourceKeyword},
{"externalchecksum", SyntaxKind.ExternalChecksumKeyword},
{"reference", SyntaxKind.ReferenceKeyword},
{"r", SyntaxKind.ReferenceKeyword},
{"enable", SyntaxKind.EnableKeyword},
{"disable", SyntaxKind.DisableKeyword}
}
......
......@@ -3783,7 +3783,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Property
'''<summary>
''' Looks up a localized string similar to &apos;If&apos;, &apos;ElseIf&apos;, &apos;Else&apos;, &apos;Const&apos;, &apos;Region&apos;, &apos;ExternalSource&apos;, &apos;ExternalChecksum&apos;, &apos;Enable&apos;, &apos;Disable&apos;, or &apos;End&apos; expected..
''' Looks up a localized string similar to &apos;If&apos;, &apos;ElseIf&apos;, &apos;Else&apos;, &apos;Const&apos;, &apos;Region&apos;, &apos;ExternalSource&apos;, &apos;ExternalChecksum&apos;, &apos;Enable&apos;, &apos;Disable&apos;, &apos;End&apos;, &apos;R&apos;, or &apos;Reference&apos; expected..
'''</summary>
Friend ReadOnly Property ERR_ExpectedConditionalDirective() As String
Get
......
......@@ -742,7 +742,7 @@
<value>'{0}' is not valid on a local variable declaration.</value>
</data>
<data name="ERR_ExpectedConditionalDirective" xml:space="preserve">
<value>'If', 'ElseIf', 'Else', 'Const', 'Region', 'ExternalSource', 'ExternalChecksum', 'Enable', 'Disable', or 'End' expected.</value>
<value>'If', 'ElseIf', 'Else', 'Const', 'Region', 'ExternalSource', 'ExternalChecksum', 'Enable', 'Disable', 'End', 'R', or 'Reference' expected.</value>
</data>
<data name="ERR_ExpectedEQ" xml:space="preserve">
<value>'=' expected.</value>
......
......@@ -1496,6 +1496,7 @@ End Class
Dim a = VisualBasicCompilation.Create("c", syntaxTrees:={ta})
' add:
Dim ab = a.AddSyntaxTrees(tb)
Assert.True(a.ReferenceManagerEquals(ab))
......@@ -1503,39 +1504,41 @@ End Class
Assert.True(a.ReferenceManagerEquals(ac))
Dim ar = a.AddSyntaxTrees(tr)
Assert.True(a.ReferenceManagerEquals(ar))
Assert.False(a.ReferenceManagerEquals(ar))
Dim arc = ar.AddSyntaxTrees(tc)
Assert.True(ar.ReferenceManagerEquals(arc))
' remove:
Dim ar2 = arc.RemoveSyntaxTrees(tc)
Assert.True(arc.ReferenceManagerEquals(ar2))
Dim c = arc.RemoveSyntaxTrees(ta, tr)
Assert.True(arc.ReferenceManagerEquals(c))
Assert.False(arc.ReferenceManagerEquals(c))
Dim none1 = c.RemoveSyntaxTrees(tc)
Assert.True(c.ReferenceManagerEquals(none1))
Dim none2 = arc.RemoveAllSyntaxTrees()
Assert.True(arc.ReferenceManagerEquals(none2))
Assert.False(arc.ReferenceManagerEquals(none2))
Dim none3 = ac.RemoveAllSyntaxTrees()
Assert.True(ac.ReferenceManagerEquals(none3))
' replace:
Dim asc = arc.ReplaceSyntaxTree(tr, ts)
Assert.True(arc.ReferenceManagerEquals(asc))
Assert.False(arc.ReferenceManagerEquals(asc))
Dim brc = arc.ReplaceSyntaxTree(ta, tb)
Assert.True(arc.ReferenceManagerEquals(brc))
Dim abc = arc.ReplaceSyntaxTree(tr, tb)
Assert.True(arc.ReferenceManagerEquals(abc))
Assert.False(arc.ReferenceManagerEquals(abc))
Dim ars = arc.ReplaceSyntaxTree(tc, ts)
Assert.True(arc.ReferenceManagerEquals(ars))
Assert.False(arc.ReferenceManagerEquals(ars))
End Sub
Private Class EvolvingTestReference
......
......@@ -102,7 +102,7 @@ Public Class SyntaxFactsTests
Assert.Equal(SyntaxKind.None, SyntaxFacts.GetContextualKeywordKind(String.Empty))
Assert.Equal(SyntaxKind.None, SyntaxFacts.GetBaseTypeStatementKind(SyntaxKind.ForKeyword))
Dim expected = New String() {"aggregate", "all", "ansi", "ascending", "assembly", "async", "auto", "await", "binary", "by", "compare", "custom", "descending", "distinct", "equals", "explicit", "externalsource", "externalchecksum", "from", "group", "infer", "into", "isfalse", "istrue", "iterator", "join", "key", "mid", "off", "order", "out", "preserve", "region", "skip", "strict", "take", "text", "unicode", "until", "where", "type", "xml", "yield", "enable", "disable", "warning"}
Dim expected = New String() {"aggregate", "all", "ansi", "ascending", "assembly", "async", "auto", "await", "binary", "by", "compare", "custom", "descending", "distinct", "equals", "explicit", "externalsource", "externalchecksum", "from", "group", "infer", "into", "isfalse", "istrue", "iterator", "join", "key", "mid", "off", "order", "out", "preserve", "region", "skip", "strict", "take", "text", "unicode", "until", "where", "type", "xml", "yield", "enable", "disable", "warning", "reference"}
For Each item In expected
Assert.NotEqual(SyntaxKind.None, SyntaxFacts.GetContextualKeywordKind(item))
Next
......
......@@ -167,6 +167,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification
SyntaxKind.ExternalSourceKeyword,
SyntaxKind.ExternalChecksumKeyword,
SyntaxKind.EnableKeyword,
SyntaxKind.ReferenceKeyword,
SyntaxKind.WarningKeyword,
SyntaxKind.DisableKeyword
......@@ -180,4 +181,4 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification
Next
End Sub
End Class
End Namespace
\ No newline at end of file
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册