diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 0d4959cb6e7ec39b2e1dfa8fb17c1501eebb8fa9..570e82e6e49c54e575ba66460fe4aaf2911ec8dc 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -378,11 +378,6 @@ internal CompilationUnitSyntax ParseCompilationUnitCore() SyntaxListBuilder attributeLists, SyntaxListBuilder modifiers) { - if (this.IsIncrementalAndFactoryContextMatches && this.CurrentNodeKind == SyntaxKind.NamespaceDeclaration) - { - return (NamespaceDeclarationSyntax)this.EatNode(); - } - Debug.Assert(this.CurrentToken.Kind == SyntaxKind.NamespaceKeyword); var namespaceToken = this.EatToken(SyntaxKind.NamespaceKeyword); @@ -2005,10 +2000,9 @@ private bool IsTypeDeclarationStart() } } - private static bool CanReuseMemberDeclaration( - CSharp.Syntax.MemberDeclarationSyntax member) + private static bool CanReuseMemberDeclaration(SyntaxKind kind) { - switch (member?.Kind()) + switch (kind) { case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: @@ -2025,6 +2019,7 @@ private bool IsTypeDeclarationStart() case SyntaxKind.DestructorDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.ConstructorDeclaration: + case SyntaxKind.NamespaceDeclaration: return true; default: return false; @@ -2075,8 +2070,7 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind // don't reuse members if they were previously declared under a different type keyword kind if (this.IsIncrementalAndFactoryContextMatches) { - var member = this.CurrentNode as CSharp.Syntax.MemberDeclarationSyntax; - if (CanReuseMemberDeclaration(member)) + if (CanReuseMemberDeclaration(CurrentNodeKind)) { return (MemberDeclarationSyntax)this.EatNode(); } diff --git a/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs index 51f49375ff04ab86724da1d3814c5165e076fcf8..1672e39c03cbdb86554ef39da34f0240eadf5bb0 100644 --- a/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs @@ -3,10 +3,7 @@ using System; using System.Collections.Immutable; using System.Linq; -using Microsoft.CodeAnalysis.CSharp.Symbols; -using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; -using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -2774,6 +2771,112 @@ class B WalkTreeAndVerify(tree.GetCompilationUnitRoot(), fullTree.GetCompilationUnitRoot()); } + [Fact] + [WorkItem(37663, "https://github.com/dotnet/roslyn/issues/37663")] + public void AssemblyAttributeBeforeNamespace() + { + var src = @" +using System; +using System.Linq; + +[assembly:] +namespace N +{ }"; + var tree = SyntaxFactory.ParseSyntaxTree(src); + var text = tree.GetText(); + var span = new TextSpan(src.IndexOf(":"), 1); + var change = new TextChange(span, ""); + text = text.WithChanges(change); + tree = tree.WithChangedText(text); + var fullTree = SyntaxFactory.ParseSyntaxTree(text.ToString()); + WalkTreeAndVerify(tree.GetCompilationUnitRoot(), fullTree.GetCompilationUnitRoot()); + } + + [WorkItem(37665, "https://github.com/dotnet/roslyn/issues/37665")] + [Fact] + public void AddBracketInUsingDirective() + { + var source = +@"using System; +namespace NS +{ + class A { } +} +"; + var tree = SyntaxFactory.ParseSyntaxTree(source); + var text = tree.GetText(); + var span = new TextSpan(source.IndexOf(";"), 0); + var change = new TextChange(span, "["); + text = text.WithChanges(change); + tree = tree.WithChangedText(text); + var fullTree = SyntaxFactory.ParseSyntaxTree(text.ToString()); + WalkTreeAndVerify(tree.GetCompilationUnitRoot(), fullTree.GetCompilationUnitRoot()); + } + + [WorkItem(37665, "https://github.com/dotnet/roslyn/issues/37665")] + [Fact] + public void AddAttributeAfterUsingDirective() + { + var source = +@"using System; +namespace NS +{ + class A { } +} +"; + var tree = SyntaxFactory.ParseSyntaxTree(source); + var text = tree.GetText(); + var span = new TextSpan(source.IndexOf(";") + 1, 0); + var change = new TextChange(span, "[Obsolete]"); + text = text.WithChanges(change); + tree = tree.WithChangedText(text); + var fullTree = SyntaxFactory.ParseSyntaxTree(text.ToString()); + WalkTreeAndVerify(tree.GetCompilationUnitRoot(), fullTree.GetCompilationUnitRoot()); + } + + [WorkItem(37665, "https://github.com/dotnet/roslyn/issues/37665")] + [Fact] + public void AddTrailingModifierInUsingDirective() + { + var source = +@"using System; +namespace NS +{ + class A { } +} +"; + var tree = SyntaxFactory.ParseSyntaxTree(source); + var text = tree.GetText(); + var span = new TextSpan(source.IndexOf(";") + 1, 0); + var change = new TextChange(span, "public"); + text = text.WithChanges(change); + tree = tree.WithChangedText(text); + var fullTree = SyntaxFactory.ParseSyntaxTree(text.ToString()); + WalkTreeAndVerify(tree.GetCompilationUnitRoot(), fullTree.GetCompilationUnitRoot()); + } + + [WorkItem(37665, "https://github.com/dotnet/roslyn/issues/37665")] + [Fact] + public void AddTrailingModifierInUsingDirective_2() + { + var source = +@"using System;publi +namespace NS +{ + class A { } +} +"; + var tree = SyntaxFactory.ParseSyntaxTree(source); + var text = tree.GetText(); + var substring = "publi"; + var span = new TextSpan(source.IndexOf(substring) + substring.Length, 0); + var change = new TextChange(span, "c"); + text = text.WithChanges(change); + tree = tree.WithChangedText(text); + var fullTree = SyntaxFactory.ParseSyntaxTree(text.ToString()); + WalkTreeAndVerify(tree.GetCompilationUnitRoot(), fullTree.GetCompilationUnitRoot()); + } + #endregion #region Helper functions