提交 bded15c7 编写于 作者: S Shyam N

Fix expander to not crash when it encounters alias that binds to a missing namespace.

Fixes #1913

When expander encounters an alias identifier that binds to a unbound namespace, it would fall through a code path that would throw NotImplementedException. This change fixes the expander to 'handle' this case without crashing (by simply retruning the IdentifierNameSyntax for the namespace that the alias binds to).

I discovered a difference in behavior between VB and C# SemanticModel which means that although I added a corresponding change to VB's expander, my fix is never invoked. I have logged #2805 for the difference and added a skipped test.
上级 f6227172
......@@ -50,6 +50,193 @@ class C
Test(input, expected)
End Sub
<WorkItem(1913, "https://github.com/dotnet/roslyn/issues/1913")>
<Fact, Trait(Traits.Feature, Traits.Features.Expansion)>
Public Sub CSharp_SimpleIdentifierAliasExpansion_AliasBinds()
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
using System;
namespace NS
{
using Short = LongNamespace;
class Test
{
public object Method1()
{
return (new {|Expand:Short|}.MyClass()).Prop;
}
}
}
namespace LongNamespace
{
public class MyClass
{
public object Prop { get; }
}
}
</Document>
</Project>
</Workspace>
Dim expected =
<code>
using System;
namespace NS
{
using Short = LongNamespace;
class Test
{
public object Method1()
{
return (new global::LongNamespace.MyClass()).Prop;
}
}
}
namespace LongNamespace
{
public class MyClass
{
public object Prop { get; }
}
}
</code>
Test(input, expected)
End Sub
<WorkItem(1913, "https://github.com/dotnet/roslyn/issues/1913")>
<Fact, Trait(Traits.Feature, Traits.Features.Expansion)>
Public Sub CSharp_SimpleIdentifierAliasExpansion_AliasDoesNotBind()
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
using System;
namespace NS
{
using Short = LongNamespace;
class Test
{
public object Method1()
{
return (new {|Expand:Short|}.MyClass()).Prop;
}
}
}
</Document>
</Project>
</Workspace>
Dim expected =
<code>
using System;
namespace NS
{
using Short = LongNamespace;
class Test
{
public object Method1()
{
return (new LongNamespace.MyClass()).Prop;
}
}
}
</code>
Test(input, expected)
End Sub
<WorkItem(1913, "https://github.com/dotnet/roslyn/issues/1913")>
<Fact, Trait(Traits.Feature, Traits.Features.Expansion)>
Public Sub VisualBasic_SimpleIdentifierAliasExpansion_AliasBinds()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Imports System
Imports ShortName = LongNamespace
Namespace NS
Class Test
Public Function Method1() As Object
Return (New {|Expand:ShortName|}.Class1()).Prop
End Function
End Class
End Namespace
Namespace LongNamespace
Public Class Class1
Public Readonly Property Prop As Object
Get
Return Nothing
End Get
End Property
End Class
End Namespace
</Document>
</Project>
</Workspace>
Dim expected =
<code>
Imports System
Imports ShortName = LongNamespace
Namespace NS
Class Test
Public Function Method1() As Object
Return (New Global.LongNamespace.Class1()).Prop
End Function
End Class
End Namespace
Namespace LongNamespace
Public Class Class1
Public Readonly Property Prop As Object
Get
Return Nothing
End Get
End Property
End Class
End Namespace
</code>
Test(input, expected)
End Sub
<WorkItem(1913, "https://github.com/dotnet/roslyn/issues/1913")>
<Fact(Skip:="https://github.com/dotnet/roslyn/issues/2805"), Trait(Traits.Feature, Traits.Features.Expansion)>
Public Sub VisualBasic_SimpleIdentifierAliasExpansion_AliasDoesNotBind()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Imports System
Imports ShortName = LongNamespace
Namespace NS
Class Test
Public Function Method1() As Object
Return (New {|Expand:ShortName|}.Class1()).Prop
End Function
End Class
End Namespace
</Document>
</Project>
</Workspace>
Dim expected =
<code>
Imports System
Imports ShortName = LongNamespace
Namespace NS
Class Test
Public Function Method1() As Object
Return (New LongNamespace.Class1()).Prop
End Function
End Class
End Namespace
</code>
Test(input, expected)
End Sub
#End Region
End Class
......
......@@ -10,14 +10,11 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.CSharp.Rename;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Utilities;
using Microsoft.CodeAnalysis.Rename.ConflictEngine;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Simplification;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Simplification
{
......@@ -381,6 +378,30 @@ private ExpressionSyntax VisitSimpleName(SimpleNameSyntax rewrittenSimpleName, S
return replacement;
}
if (replacement.IsKind(SyntaxKind.IdentifierName))
{
var identifierReplacement = (IdentifierNameSyntax)replacement;
var newIdentifier = identifier.CopyAnnotationsTo(identifierReplacement.Identifier);
if (_annotationForReplacedAliasIdentifier != null)
{
newIdentifier = newIdentifier.WithAdditionalAnnotations(_annotationForReplacedAliasIdentifier);
}
var aliasAnnotationInfo = AliasAnnotation.Create(aliasInfo.Name);
newIdentifier = newIdentifier.WithAdditionalAnnotations(aliasAnnotationInfo);
replacement = replacement.ReplaceToken(identifier, newIdentifier);
replacement = newNode.CopyAnnotationsTo(replacement);
replacement = AppendElasticTriviaIfNecessary(replacement, originalSimpleName);
return replacement;
}
throw new NotImplementedException();
}
}
......
......@@ -3,9 +3,7 @@
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Simplification
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.Rename
Imports Microsoft.CodeAnalysis.VisualBasic.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
......@@ -468,6 +466,25 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification
Return replacement
End If
If replacement.IsKind(SyntaxKind.IdentifierName) Then
Dim identifierReplacement = DirectCast(replacement, IdentifierNameSyntax)
Dim newIdentifier = identifier.CopyAnnotationsTo(identifierReplacement.Identifier)
If Me._annotationForReplacedAliasIdentifier IsNot Nothing Then
newIdentifier = newIdentifier.WithAdditionalAnnotations(Me._annotationForReplacedAliasIdentifier)
End If
Dim aliasAnnotationInfo = AliasAnnotation.Create(aliasInfo.Name)
newIdentifier = newIdentifier.WithAdditionalAnnotations(aliasAnnotationInfo)
replacement = replacement.ReplaceToken(identifier, newIdentifier)
replacement = newNode.CopyAnnotationsTo(replacement)
Return replacement
End If
Throw New NotImplementedException()
End If
End If
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册