提交 362a5d01 编写于 作者: L lorcanmooney

Add namespace-name suggestions for VB

上级 d20421ec
...@@ -432,35 +432,90 @@ public async Task NamespaceName_Unqualified_ExcludesCurrentDeclaration() ...@@ -432,35 +432,90 @@ public async Task NamespaceName_Unqualified_ExcludesCurrentDeclaration()
await VerifyItemIsAbsentAsync(source, "NS"); await VerifyItemIsAbsentAsync(source, "NS");
} }
// [WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")] [WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
// [Fact, Trait(Traits.Feature, Traits.Features.Completion)] [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
// public async Task NamespaceName_Unqualified_IncompleteDeclaration() public async Task NamespaceName_Unqualified_WithNested()
// { {
// var source = @" var source = @"
//namespace A.B.C0 { } namespace A
// {
//namespace A namespace $$
//{ {
// namespace B namespace B { }
// { }
// namespace C$$ }";
//
// namespace C1.X { } await VerifyItemIsAbsentAsync(source, "A");
// } await VerifyItemIsAbsentAsync(source, "B");
// }
// namespace B.C2.Y { }
//} [WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
// [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
//namespace A.B.C3.Z { }"; public async Task NamespaceName_Unqualified_WithNestedAndMatchingPeer()
// {
// await VerifyItemIsAbsentAsync(source, "C0"); var source = @"
// await VerifyItemExistsAsync(source, "C1"); namespace A.B { }
// await VerifyItemExistsAsync(source, "C2");
// await VerifyItemExistsAsync(source, "C3"); namespace A
// await VerifyItemIsAbsentAsync(source, "X"); {
// await VerifyItemIsAbsentAsync(source, "Y"); namespace $$
// await VerifyItemIsAbsentAsync(source, "Z"); {
// } namespace B { }
}
}";
await VerifyItemIsAbsentAsync(source, "A");
await VerifyItemExistsAsync(source, "B");
}
[WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task NamespaceName_Unqualified_InnerCompletionPosition()
{
var source = @"namespace Sys$$tem { }";
await VerifyItemExistsAsync(source, "System");
await VerifyItemIsAbsentAsync(source, "Runtime");
}
[WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task NamespaceName_Unqualified_IncompleteDeclaration()
{
var source = @"
namespace A
{
namespace B
{
namespace $$
namespace C1 { }
}
namespace B.C2 { }
}
namespace A.B.C3 { }";
// Ideally, all the C* namespaces would be recommended but, because of how the parser
// recovers from the missing braces, they end up with the following qualified names...
//
// C1 => A.B.?.C1
// C2 => A.B.B.C2
// C3 => A.A.B.C3
//
// ...none of which are found by the current algorithm.
await VerifyItemIsAbsentAsync(source, "C1");
await VerifyItemIsAbsentAsync(source, "C2");
await VerifyItemIsAbsentAsync(source, "C3");
await VerifyItemIsAbsentAsync(source, "A");
// Because of the above, B does end up in the completion list
// since A.B.B appears to be a peer of the new declaration
await VerifyItemExistsAsync(source, "B");
}
[WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")] [WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)] [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
...@@ -500,35 +555,83 @@ namespace B.$$ ...@@ -500,35 +555,83 @@ namespace B.$$
await VerifyItemExistsAsync(source, "C"); await VerifyItemExistsAsync(source, "C");
} }
// [WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")] [WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
// [Fact, Trait(Traits.Feature, Traits.Features.Completion)] [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
// public async Task NamespaceName_Qualified_IncompleteDeclaration() public async Task NamespaceName_Qualified_WithNested()
// { {
// var source = @" var source = @"
//namespace A.B.C.D0 { } namespace A.$$
// {
//namespace A namespace B { }
//{ }
// namespace B ";
// {
// namespace C.D$$ await VerifyItemIsAbsentAsync(source, "A");
// await VerifyItemIsAbsentAsync(source, "B");
// namespace C.D1.X { } }
// }
// [WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
// namespace B.C.D2.Y { } [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
//} public async Task NamespaceName_Qualified_WithNestedAndMatchingPeer()
// {
//namespace A.B.C.D3.Z { }"; var source = @"
// namespace A.B { }
// await VerifyItemIsAbsentAsync(source, "D0");
// await VerifyItemExistsAsync(source, "D1"); namespace A.$$
// await VerifyItemExistsAsync(source, "D2"); {
// await VerifyItemExistsAsync(source, "D3"); namespace B { }
// await VerifyItemIsAbsentAsync(source, "X"); }
// await VerifyItemIsAbsentAsync(source, "Y"); ";
// await VerifyItemIsAbsentAsync(source, "Z");
// } await VerifyItemIsAbsentAsync(source, "A");
await VerifyItemExistsAsync(source, "B");
}
[WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task NamespaceName_Qualified_InnerCompletionPosition()
{
var source = @"namespace Sys$$tem.Runtime { }";
await VerifyItemExistsAsync(source, "System");
await VerifyItemIsAbsentAsync(source, "Runtime");
}
[WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task NamespaceName_Qualified_IncompleteDeclaration()
{
var source = @"
namespace A
{
namespace B
{
namespace C.$$
namespace C.D1 { }
}
namespace B.C.D2 { }
}
namespace A.B.C.D3 { }";
await VerifyItemIsAbsentAsync(source, "A");
await VerifyItemIsAbsentAsync(source, "B");
await VerifyItemIsAbsentAsync(source, "C");
// Ideally, all the D* namespaces would be recommended but, because of how the parser
// recovers from the missing braces, they end up with the following qualified names...
//
// D1 => A.B.C.C.?.D1
// D2 => A.B.B.C.D2
// D3 => A.A.B.C.D3
//
// ...none of which are found by the current algorithm.
await VerifyItemIsAbsentAsync(source, "D1");
await VerifyItemIsAbsentAsync(source, "D2");
await VerifyItemIsAbsentAsync(source, "D3");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)] [Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task UnderNamespace() public async Task UnderNamespace()
......
...@@ -108,7 +108,7 @@ private async Task CheckResultsAsync(Document document, int position, string exp ...@@ -108,7 +108,7 @@ private async Task CheckResultsAsync(Document document, int position, string exp
var completionService = GetCompletionService(document.Project.Solution.Workspace); var completionService = GetCompletionService(document.Project.Solution.Workspace);
var completionList = await GetCompletionListAsync(completionService, document, position, trigger); var completionList = await GetCompletionListAsync(completionService, document, position, trigger);
var items = completionList == null ? default(ImmutableArray<CompletionItem>) : completionList.Items; var items = completionList == null ? ImmutableArray<CompletionItem>.Empty : completionList.Items;
if (checkForAbsence) if (checkForAbsence)
{ {
......
...@@ -303,6 +303,26 @@ End Class ...@@ -303,6 +303,26 @@ End Class
Await VerifyBuilderAsync(markup, CompletionTrigger.Default, useDebuggerOptions:=True) Await VerifyBuilderAsync(markup, CompletionTrigger.Default, useDebuggerOptions:=True)
End Function End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceDeclarationName_Unqualified() As Task
Dim markup = <a>
Namespace $$
End Class
</a>
Await VerifyBuilderAsync(markup, CompletionTrigger.Default)
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceDeclarationName_Qualified() As Task
Dim markup = <a>
Namespace A.$$
End Class
</a>
Await VerifyBuilderAsync(markup, CompletionTrigger.Default)
End Function
Private Function VerifyNotBuilderAsync(markup As XElement, Optional triggerInfo As CompletionTrigger? = Nothing, Optional useDebuggerOptions As Boolean = False) As Task Private Function VerifyNotBuilderAsync(markup As XElement, Optional triggerInfo As CompletionTrigger? = Nothing, Optional useDebuggerOptions As Boolean = False) As Task
Return VerifySuggestionModeWorkerAsync(markup, isBuilder:=False, triggerInfo:=triggerInfo, useDebuggerOptions:=useDebuggerOptions) Return VerifySuggestionModeWorkerAsync(markup, isBuilder:=False, triggerInfo:=triggerInfo, useDebuggerOptions:=useDebuggerOptions)
End Function End Function
......
...@@ -5747,6 +5747,317 @@ End Module ...@@ -5747,6 +5747,317 @@ End Module
Await VerifyItemExistsAsync(text, "D") Await VerifyItemExistsAsync(text, "D")
End Function End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Unqualified_TopLevelNoPeers() As Task
Dim source = <code><![CDATA[
Imports System;
Namespace $$
]]></code>.Value
Await VerifyItemExistsAsync(source, "System")
Await VerifyItemIsAbsentAsync(source, "String")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Unqualified_TopLevelWithPeer() As Task
Dim source = <code><![CDATA[
Namespace A
End Namespace
Namespace $$
]]></code>.Value
Await VerifyItemExistsAsync(source, "A")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Unqualified_NestedWithNoPeers() As Task
Dim source = <code><![CDATA[
Namespace A
Namespace $$
End Namespace
]]></code>.Value
Await VerifyNoItemsExistAsync(source)
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Unqualified_NestedWithPeer() As Task
Dim source = <code><![CDATA[
Namespace A
Namespace B
End Namespace
Namespace $$
End Namespace
]]></code>.Value
Await VerifyItemIsAbsentAsync(source, "A")
Await VerifyItemExistsAsync(source, "B")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Unqualified_ExcludesCurrentDeclaration() As Task
Dim source = <code><![CDATA[Namespace N$$S]]></code>.Value
Await VerifyItemIsAbsentAsync(source, "NS")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Unqualified_WithNested() As Task
Dim source = <code><![CDATA[
Namespace A
Namespace $$
Namespace B
End Namespace
End Namespace
End Namespace
]]></code>.Value
Await VerifyItemIsAbsentAsync(source, "A")
Await VerifyItemIsAbsentAsync(source, "B")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Unqualified_WithNestedAndMatchingPeer() As Task
Dim source = <code><![CDATA[
Namespace A.B
End Namespace
Namespace A
Namespace $$
Namespace B
End Namespace
End Namespace
End Namespace
]]></code>.Value
Await VerifyItemIsAbsentAsync(source, "A")
Await VerifyItemExistsAsync(source, "B")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Unqualified_InnerCompletionPosition() As Task
Dim source = <code><![CDATA[
Namespace Sys$$tem
End Namespace
]]></code>.Value
Await VerifyItemExistsAsync(source, "System")
Await VerifyItemIsAbsentAsync(source, "Runtime")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Unqualified_IncompleteDeclaration() As Task
Dim source = <code><![CDATA[
Namespace A
Namespace B
Namespace $$
Namespace C1
End Namespace
End Namespace
Namespace B.C2
End Namespace
End Namespace
Namespace A.B.C3
End Namespace
]]></code>.Value
' Ideally, all the C* namespaces would be recommended but, because of how the parser
' recovers from the missing end statement, they end up with the following qualified names...
'
' C1 => A.B.?.C1
' C2 => A.B.B.C2
' C3 => A.A.B.C3
'
' ...none of which are found by the current algorithm.
Await VerifyItemIsAbsentAsync(source, "C1")
Await VerifyItemIsAbsentAsync(source, "C2")
Await VerifyItemIsAbsentAsync(source, "C3")
Await VerifyItemIsAbsentAsync(source, "A")
' Because of the above, B does end up in the completion list
' since A.B.B appears to be a peer of the New declaration
Await VerifyItemExistsAsync(source, "B")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Qualified_NoPeers() As Task
Dim source = <code><![CDATA[Namespace A.$$]]></code>.Value
Await VerifyNoItemsExistAsync(source)
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Qualified_TopLevelWithPeer() As Task
Dim source = <code><![CDATA[
Namespace A.B
End Namespace
Namespace A.$$
]]></code>.Value
Await VerifyItemExistsAsync(source, "B")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Qualified_NestedWithPeer() As Task
Dim source = <code><![CDATA[
Namespace A
Namespace B.C
End Namespace
Namespace B.$$
End Namespace
]]></code>.Value
Await VerifyItemIsAbsentAsync(source, "A")
Await VerifyItemIsAbsentAsync(source, "B")
Await VerifyItemExistsAsync(source, "C")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Qualified_WithNested() As Task
Dim source = <code><![CDATA[
Namespace A.$$
Namespace B
End Namespace
End Namespace
]]></code>.Value
Await VerifyItemIsAbsentAsync(source, "A")
Await VerifyItemIsAbsentAsync(source, "B")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Qualified_WithNestedAndMatchingPeer() As Task
Dim source = <code><![CDATA[
Namespace A.B
End Namespace
Namespace A.$$
Namespace B
End Namespace
End Namespace
]]></code>.Value
Await VerifyItemIsAbsentAsync(source, "A")
Await VerifyItemExistsAsync(source, "B")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Qualified_InnerCompletionPosition() As Task
Dim source = <code><![CDATA[
Namespace Sys$$tem.Runtim
End Namespace
]]></code>.Value
Await VerifyItemExistsAsync(source, "System")
Await VerifyItemIsAbsentAsync(source, "Runtime")
End Function
<WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function NamespaceName_Qualified_IncompleteDeclaration() As Task
Dim source = <code><![CDATA[
Namespace A
Namespace B
Namespace C.$$
Namespace C.D1
End Namespace
End Namespace
Namespace B.C.D2
End Namespace
End Namespace
Namespace A.B.C.D3
End Namespace
]]></code>.Value
Await VerifyItemIsAbsentAsync(source, "A")
Await VerifyItemIsAbsentAsync(source, "B")
Await VerifyItemIsAbsentAsync(source, "C")
' Ideally, all the D* namespaces would be recommended but, because of how the parser
' recovers from the end statement, they end up with the following qualified names...
'
' D1 => A.B.C.C.?.D1
' D2 => A.B.B.C.D2
' D3 => A.A.B.C.D3
'
' ...none of which are found by the current algorithm.
Await VerifyItemIsAbsentAsync(source, "D1")
Await VerifyItemIsAbsentAsync(source, "D2")
Await VerifyItemIsAbsentAsync(source, "D3")
End Function
<WorkItem(925469, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/925469")> <WorkItem(925469, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/925469")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)> <Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function CommitWithCloseBracketLeaveOpeningBracket1() As Task Public Async Function CommitWithCloseBracketLeaveOpeningBracket1() As Task
......
...@@ -79,6 +79,15 @@ internal class CSharpFeaturesResources { ...@@ -79,6 +79,15 @@ internal class CSharpFeaturesResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Autoselect disabled due to namespace declaration..
/// </summary>
internal static string AutoselectDisabledDueToNamespaceDeclaration {
get {
return ResourceManager.GetString("AutoselectDisabledDueToNamespaceDeclaration", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Autoselect disabled due to possible explicitly named anonymous type member creation.. /// Looks up a localized string similar to Autoselect disabled due to possible explicitly named anonymous type member creation..
/// </summary> /// </summary>
...@@ -565,6 +574,15 @@ internal class CSharpFeaturesResources { ...@@ -565,6 +574,15 @@ internal class CSharpFeaturesResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to &lt;namespace name&gt;.
/// </summary>
internal static string NamespaceName {
get {
return ResourceManager.GetString("NamespaceName", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to No common root node for extraction.. /// Looks up a localized string similar to No common root node for extraction..
/// </summary> /// </summary>
......
...@@ -455,4 +455,10 @@ ...@@ -455,4 +455,10 @@
<data name="UseImplicitTypeDiagnosticTitle" xml:space="preserve"> <data name="UseImplicitTypeDiagnosticTitle" xml:space="preserve">
<value>Use implicit type</value> <value>Use implicit type</value>
</data> </data>
<data name="AutoselectDisabledDueToNamespaceDeclaration" xml:space="preserve">
<value>Autoselect disabled due to namespace declaration.</value>
</data>
<data name="NamespaceName" xml:space="preserve">
<value>&lt;namespace name&gt;</value>
</data>
</root> </root>
\ No newline at end of file
...@@ -61,7 +61,7 @@ protected override async Task<CompletionItem> GetSuggestionModeItemAsync(Documen ...@@ -61,7 +61,7 @@ protected override async Task<CompletionItem> GetSuggestionModeItemAsync(Documen
} }
else if (tree.IsNamespaceDeclarationNameContext(position, cancellationToken)) else if (tree.IsNamespaceDeclarationNameContext(position, cancellationToken))
{ {
return CreateEmptySuggestionModeItem(itemSpan); return CreateSuggestionModeItem(CSharpFeaturesResources.NamespaceName, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToNamespaceDeclaration);
} }
} }
......
...@@ -5,7 +5,6 @@ Imports Microsoft.CodeAnalysis ...@@ -5,7 +5,6 @@ Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Completion Imports Microsoft.CodeAnalysis.Completion
Imports Microsoft.CodeAnalysis.Completion.SuggestionMode Imports Microsoft.CodeAnalysis.Completion.SuggestionMode
Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
...@@ -94,6 +93,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.SuggestionMode ...@@ -94,6 +93,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.SuggestionMode
Return CreateSuggestionModeItem(VBFeaturesResources.NewResource, itemSpan, description) Return CreateSuggestionModeItem(VBFeaturesResources.NewResource, itemSpan, description)
End If End If
' Builder at Namespace declaration name
If syntaxTree.IsNamespaceDeclarationNameContext(position, cancellationToken) Then
description = VBFeaturesResources.TypeANameHereToDeclareANamespace & vbCrLf &
VBFeaturesResources.NoteSpaceAndCompletion
Return CreateSuggestionModeItem(VBFeaturesResources.NamespaceName, itemSpan, description)
End If
Return Nothing Return Nothing
End Function End Function
......
...@@ -1865,6 +1865,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources ...@@ -1865,6 +1865,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized string similar to &lt;namespace name&gt;.
'''</summary>
Friend ReadOnly Property NamespaceName() As String
Get
Return ResourceManager.GetString("NamespaceName", resourceCulture)
End Get
End Property
'''<summary> '''<summary>
''' Looks up a localized string similar to Indicates that a conversion operator (CType) converts a class or structure to a type that might not be able to hold some of the possible values of the original class or structure.. ''' Looks up a localized string similar to Indicates that a conversion operator (CType) converts a class or structure to a type that might not be able to hold some of the possible values of the original class or structure..
'''</summary> '''</summary>
...@@ -2913,6 +2922,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources ...@@ -2913,6 +2922,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized string similar to Type a name here to declare a namespace..
'''</summary>
Friend ReadOnly Property TypeANameHereToDeclareANamespace() As String
Get
Return ResourceManager.GetString("TypeANameHereToDeclareANamespace", resourceCulture)
End Get
End Property
'''<summary> '''<summary>
''' Looks up a localized string similar to Type a new name for the column, followed by &apos;=&apos;. Otherwise, the original column name with be used.. ''' Looks up a localized string similar to Type a new name for the column, followed by &apos;=&apos;. Otherwise, the original column name with be used..
'''</summary> '''</summary>
......
...@@ -1204,4 +1204,10 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</value> ...@@ -1204,4 +1204,10 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</value>
<data name="Properties" xml:space="preserve"> <data name="Properties" xml:space="preserve">
<value>Properties</value> <value>Properties</value>
</data> </data>
<data name="NamespaceName" xml:space="preserve">
<value>&lt;namespace name&gt;</value>
</data>
<data name="TypeANameHereToDeclareANamespace" xml:space="preserve">
<value>Type a name here to declare a namespace.</value>
</data>
</root> </root>
\ No newline at end of file
...@@ -27,7 +27,6 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext ...@@ -27,7 +27,6 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext
public readonly bool IsLabelContext; public readonly bool IsLabelContext;
public readonly bool IsTypeArgumentOfConstraintContext; public readonly bool IsTypeArgumentOfConstraintContext;
public readonly bool IsNamespaceDeclarationNameContext;
public readonly bool IsIsOrAsContext; public readonly bool IsIsOrAsContext;
public readonly bool IsObjectCreationTypeContext; public readonly bool IsObjectCreationTypeContext;
public readonly bool IsDefiniteCastTypeContext; public readonly bool IsDefiniteCastTypeContext;
...@@ -63,6 +62,7 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext ...@@ -63,6 +62,7 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext
bool isPreProcessorExpressionContext, bool isPreProcessorExpressionContext,
bool isTypeContext, bool isTypeContext,
bool isNamespaceContext, bool isNamespaceContext,
bool isNamespaceDeclarationNameContext,
bool isStatementContext, bool isStatementContext,
bool isGlobalStatementContext, bool isGlobalStatementContext,
bool isAnyExpressionContext, bool isAnyExpressionContext,
...@@ -75,7 +75,6 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext ...@@ -75,7 +75,6 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext
bool isInImportsDirective, bool isInImportsDirective,
bool isLabelContext, bool isLabelContext,
bool isTypeArgumentOfConstraintContext, bool isTypeArgumentOfConstraintContext,
bool isNamespaceDeclarationNameContext,
bool isRightOfDotOrArrowOrColonColon, bool isRightOfDotOrArrowOrColonColon,
bool isIsOrAsContext, bool isIsOrAsContext,
bool isObjectCreationTypeContext, bool isObjectCreationTypeContext,
...@@ -98,7 +97,7 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext ...@@ -98,7 +97,7 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext
bool isCatchFilterContext, bool isCatchFilterContext,
bool isDestructorTypeContext) bool isDestructorTypeContext)
: base(workspace, semanticModel, position, leftToken, targetToken, : base(workspace, semanticModel, position, leftToken, targetToken,
isTypeContext, isNamespaceContext, isTypeContext, isNamespaceContext, isNamespaceDeclarationNameContext,
isPreProcessorDirectiveContext, isPreProcessorDirectiveContext,
isRightOfDotOrArrowOrColonColon, isStatementContext, isAnyExpressionContext, isRightOfDotOrArrowOrColonColon, isStatementContext, isAnyExpressionContext,
isAttributeNameContext, isEnumTypeMemberAccessContext, isNameOfContext, isAttributeNameContext, isEnumTypeMemberAccessContext, isNameOfContext,
...@@ -114,7 +113,6 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext ...@@ -114,7 +113,6 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext
this.IsConstantExpressionContext = isConstantExpressionContext; this.IsConstantExpressionContext = isConstantExpressionContext;
this.IsLabelContext = isLabelContext; this.IsLabelContext = isLabelContext;
this.IsTypeArgumentOfConstraintContext = isTypeArgumentOfConstraintContext; this.IsTypeArgumentOfConstraintContext = isTypeArgumentOfConstraintContext;
this.IsNamespaceDeclarationNameContext = isNamespaceDeclarationNameContext;
this.IsIsOrAsContext = isIsOrAsContext; this.IsIsOrAsContext = isIsOrAsContext;
this.IsObjectCreationTypeContext = isObjectCreationTypeContext; this.IsObjectCreationTypeContext = isObjectCreationTypeContext;
this.IsDefiniteCastTypeContext = isDefiniteCastTypeContext; this.IsDefiniteCastTypeContext = isDefiniteCastTypeContext;
...@@ -201,6 +199,7 @@ public static CSharpSyntaxContext CreateContext(Workspace workspace, SemanticMod ...@@ -201,6 +199,7 @@ public static CSharpSyntaxContext CreateContext(Workspace workspace, SemanticMod
isPreProcessorExpressionContext, isPreProcessorExpressionContext,
syntaxTree.IsTypeContext(position, cancellationToken, semanticModelOpt: semanticModel), syntaxTree.IsTypeContext(position, cancellationToken, semanticModelOpt: semanticModel),
syntaxTree.IsNamespaceContext(position, cancellationToken, semanticModelOpt: semanticModel), syntaxTree.IsNamespaceContext(position, cancellationToken, semanticModelOpt: semanticModel),
syntaxTree.IsNamespaceDeclarationNameContext(position, cancellationToken),
isStatementContext, isStatementContext,
isGlobalStatementContext, isGlobalStatementContext,
isAnyExpressionContext, isAnyExpressionContext,
...@@ -213,7 +212,6 @@ public static CSharpSyntaxContext CreateContext(Workspace workspace, SemanticMod ...@@ -213,7 +212,6 @@ public static CSharpSyntaxContext CreateContext(Workspace workspace, SemanticMod
IsLeftSideOfUsingAliasDirective(leftToken, cancellationToken), IsLeftSideOfUsingAliasDirective(leftToken, cancellationToken),
syntaxTree.IsLabelContext(position, cancellationToken), syntaxTree.IsLabelContext(position, cancellationToken),
syntaxTree.IsTypeArgumentOfConstraintClause(position, cancellationToken), syntaxTree.IsTypeArgumentOfConstraintClause(position, cancellationToken),
syntaxTree.IsNamespaceDeclarationNameContext(position, cancellationToken),
syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken), syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken),
syntaxTree.IsIsOrAsContext(position, leftToken, cancellationToken), syntaxTree.IsIsOrAsContext(position, leftToken, cancellationToken),
syntaxTree.IsObjectCreationTypeContext(position, leftToken, cancellationToken), syntaxTree.IsObjectCreationTypeContext(position, leftToken, cancellationToken),
......
...@@ -603,6 +603,18 @@ public static bool IsAttributeNameContext(this SyntaxTree syntaxTree, int positi ...@@ -603,6 +603,18 @@ public static bool IsAttributeNameContext(this SyntaxTree syntaxTree, int positi
return syntaxTree.IsTypeContext(position, cancellationToken, semanticModelOpt); return syntaxTree.IsTypeContext(position, cancellationToken, semanticModelOpt);
} }
public static bool IsNamespaceDeclarationNameContext(this SyntaxTree syntaxTree, int position, CancellationToken cancellationToken)
{
var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken);
var namespaceDeclaration = token.GetAncestor<NamespaceDeclarationSyntax>();
if (namespaceDeclaration == null)
{
return false;
}
return namespaceDeclaration.Name.Span.IntersectsWith(position) || token == namespaceDeclaration.NamespaceKeyword;
}
public static bool IsDefinitelyNotTypeContext(this SyntaxTree syntaxTree, int position, CancellationToken cancellationToken) public static bool IsDefinitelyNotTypeContext(this SyntaxTree syntaxTree, int position, CancellationToken cancellationToken)
{ {
return return
......
...@@ -111,18 +111,6 @@ private static bool BaseTypeDeclarationContainsPosition(BaseTypeDeclarationSynta ...@@ -111,18 +111,6 @@ private static bool BaseTypeDeclarationContainsPosition(BaseTypeDeclarationSynta
private static readonly Func<SyntaxKind, bool> s_isDotOrArrowOrColonColon = private static readonly Func<SyntaxKind, bool> s_isDotOrArrowOrColonColon =
k => k == SyntaxKind.DotToken || k == SyntaxKind.MinusGreaterThanToken || k == SyntaxKind.ColonColonToken; k => k == SyntaxKind.DotToken || k == SyntaxKind.MinusGreaterThanToken || k == SyntaxKind.ColonColonToken;
public static bool IsNamespaceDeclarationNameContext(this SyntaxTree syntaxTree, int position, CancellationToken cancellationToken)
{
var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken);
var namespaceDeclaration = token.GetAncestor<NamespaceDeclarationSyntax>();
if (namespaceDeclaration == null)
{
return false;
}
return namespaceDeclaration.Name.Span.IntersectsWith(position) || token == namespaceDeclaration.NamespaceKeyword;
}
public static bool IsRightOfDotOrArrowOrColonColon(this SyntaxTree syntaxTree, int position, CancellationToken cancellationToken) public static bool IsRightOfDotOrArrowOrColonColon(this SyntaxTree syntaxTree, int position, CancellationToken cancellationToken)
{ {
return syntaxTree.IsRightOf(position, s_isDotOrArrowOrColonColon, cancellationToken); return syntaxTree.IsRightOf(position, s_isDotOrArrowOrColonColon, cancellationToken);
......
...@@ -80,7 +80,7 @@ internal class CSharpRecommendationService : AbstractRecommendationService ...@@ -80,7 +80,7 @@ internal class CSharpRecommendationService : AbstractRecommendationService
} }
else if (context.IsTypeContext || context.IsNamespaceContext) else if (context.IsTypeContext || context.IsNamespaceContext)
{ {
return GetSymbolsForTypeOrNamespaceContext(context, cancellationToken); return GetSymbolsForTypeOrNamespaceContext(context);
} }
else if (context.IsLabelContext) else if (context.IsLabelContext)
{ {
...@@ -217,9 +217,7 @@ internal class CSharpRecommendationService : AbstractRecommendationService ...@@ -217,9 +217,7 @@ internal class CSharpRecommendationService : AbstractRecommendationService
.AsImmutableOrEmpty(); .AsImmutableOrEmpty();
} }
private static IEnumerable<ISymbol> GetSymbolsForTypeOrNamespaceContext( private static IEnumerable<ISymbol> GetSymbolsForTypeOrNamespaceContext(CSharpSyntaxContext context)
CSharpSyntaxContext context,
CancellationToken cancellationToken)
{ {
var symbols = context.SemanticModel.LookupNamespacesAndTypes(context.LeftToken.SpanStart); var symbols = context.SemanticModel.LookupNamespacesAndTypes(context.LeftToken.SpanStart);
...@@ -236,20 +234,10 @@ internal class CSharpRecommendationService : AbstractRecommendationService ...@@ -236,20 +234,10 @@ internal class CSharpRecommendationService : AbstractRecommendationService
return symbols; return symbols;
} }
private static IEnumerable<ISymbol> GetSymbolsForNamespaceDeclarationNameContext( private static IEnumerable<ISymbol> GetSymbolsForNamespaceDeclarationNameContext(CSharpSyntaxContext context, CancellationToken cancellationToken)
CSharpSyntaxContext context,
CancellationToken cancellationToken)
{ {
var namespaceDeclaration = context.TargetToken.GetAncestor<NamespaceDeclarationSyntax>(); var declarationSyntax = context.TargetToken.GetAncestor<NamespaceDeclarationSyntax>();
return GetRecommendedNamespaceNameSymbols(context.SemanticModel, declarationSyntax, cancellationToken);
var declaredNamespaceSymbol = context.SemanticModel.GetDeclaredSymbol(namespaceDeclaration);
var containingNamespaceSymbol = context.SemanticModel.Compilation.GetCompilationNamespace(declaredNamespaceSymbol.ContainingNamespace);
var symbols = context.SemanticModel
.LookupNamespacesAndTypes(context.LeftToken.SpanStart, containingNamespaceSymbol)
.Where(symbol => IsNonIntersectingNamespace(symbol, context));
return symbols;
} }
private static IEnumerable<ISymbol> GetSymbolsForExpressionOrStatementContext( private static IEnumerable<ISymbol> GetSymbolsForExpressionOrStatementContext(
...@@ -337,7 +325,8 @@ internal class CSharpRecommendationService : AbstractRecommendationService ...@@ -337,7 +325,8 @@ internal class CSharpRecommendationService : AbstractRecommendationService
if (context.IsNamespaceDeclarationNameContext) if (context.IsNamespaceDeclarationNameContext)
{ {
return symbols.Where(s => IsNonIntersectingNamespace(s, context)); NamespaceDeclarationSyntax declarationSyntax = name.GetAncestorOrThis<NamespaceDeclarationSyntax>();
return symbols.Where(s => IsNonIntersectingNamespace(s, declarationSyntax));
} }
// Filter the types when in a using directive, but not an alias. // Filter the types when in a using directive, but not an alias.
...@@ -369,11 +358,6 @@ internal class CSharpRecommendationService : AbstractRecommendationService ...@@ -369,11 +358,6 @@ internal class CSharpRecommendationService : AbstractRecommendationService
return SpecializedCollections.EmptyEnumerable<ISymbol>(); return SpecializedCollections.EmptyEnumerable<ISymbol>();
} }
private static bool IsNonIntersectingNamespace(ISymbol symbol, CSharpSyntaxContext context)
{
return symbol.IsNamespace() && symbol.Locations.Any(location => !context.IntersectsWith(location));
}
private static IEnumerable<ISymbol> GetSymbolsOffOfExpression( private static IEnumerable<ISymbol> GetSymbolsOffOfExpression(
CSharpSyntaxContext context, CSharpSyntaxContext context,
ExpressionSyntax originalExpression, ExpressionSyntax originalExpression,
......
...@@ -29,6 +29,26 @@ internal abstract class AbstractRecommendationService : IRecommendationService ...@@ -29,6 +29,26 @@ internal abstract class AbstractRecommendationService : IRecommendationService
return symbols; return symbols;
} }
protected static IEnumerable<ISymbol> GetRecommendedNamespaceNameSymbols(
SemanticModel semanticModel, SyntaxNode declarationSyntax, CancellationToken cancellationToken)
{
var containingNamespaceSymbol = semanticModel.Compilation.GetCompilationNamespace(
semanticModel.GetEnclosingNamespace(declarationSyntax.SpanStart, cancellationToken));
var symbols = semanticModel.LookupNamespacesAndTypes(declarationSyntax.SpanStart, containingNamespaceSymbol)
.Where(recommendationSymbol => IsNonIntersectingNamespace(recommendationSymbol, declarationSyntax));
return symbols;
}
protected static bool IsNonIntersectingNamespace(ISymbol recommendationSymbol, SyntaxNode declarationSyntax)
{
return recommendationSymbol.IsNamespace() &&
recommendationSymbol.Locations.Any(
candidateLocation => !(declarationSyntax.SyntaxTree == candidateLocation.SourceTree &&
declarationSyntax.Span.IntersectsWith(candidateLocation.SourceSpan)));
}
private sealed class ShouldIncludeSymbolContext private sealed class ShouldIncludeSymbolContext
{ {
private readonly AbstractSyntaxContext _context; private readonly AbstractSyntaxContext _context;
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host;
...@@ -20,6 +19,7 @@ internal abstract class AbstractSyntaxContext ...@@ -20,6 +19,7 @@ internal abstract class AbstractSyntaxContext
SyntaxToken targetToken, SyntaxToken targetToken,
bool isTypeContext, bool isTypeContext,
bool isNamespaceContext, bool isNamespaceContext,
bool isNamespaceDeclarationNameContext,
bool isPreProcessorDirectiveContext, bool isPreProcessorDirectiveContext,
bool isRightOfNameSeparator, bool isRightOfNameSeparator,
bool isStatementContext, bool isStatementContext,
...@@ -38,6 +38,7 @@ internal abstract class AbstractSyntaxContext ...@@ -38,6 +38,7 @@ internal abstract class AbstractSyntaxContext
this.TargetToken = targetToken; this.TargetToken = targetToken;
this.IsTypeContext = isTypeContext; this.IsTypeContext = isTypeContext;
this.IsNamespaceContext = isNamespaceContext; this.IsNamespaceContext = isNamespaceContext;
this.IsNamespaceDeclarationNameContext = isNamespaceDeclarationNameContext;
this.IsPreProcessorDirectiveContext = isPreProcessorDirectiveContext; this.IsPreProcessorDirectiveContext = isPreProcessorDirectiveContext;
this.IsRightOfNameSeparator = isRightOfNameSeparator; this.IsRightOfNameSeparator = isRightOfNameSeparator;
this.IsStatementContext = isStatementContext; this.IsStatementContext = isStatementContext;
...@@ -60,6 +61,8 @@ internal abstract class AbstractSyntaxContext ...@@ -60,6 +61,8 @@ internal abstract class AbstractSyntaxContext
public bool IsTypeContext { get; } public bool IsTypeContext { get; }
public bool IsNamespaceContext { get; } public bool IsNamespaceContext { get; }
public bool IsNamespaceDeclarationNameContext { get; }
public bool IsPreProcessorDirectiveContext { get; } public bool IsPreProcessorDirectiveContext { get; }
public bool IsRightOfNameSeparator { get; } public bool IsRightOfNameSeparator { get; }
...@@ -106,15 +109,5 @@ public ISet<INamedTypeSymbol> GetOuterTypes(CancellationToken cancellationToken) ...@@ -106,15 +109,5 @@ public ISet<INamedTypeSymbol> GetOuterTypes(CancellationToken cancellationToken)
{ {
return this.Workspace.Services.GetService<TService>(); return this.Workspace.Services.GetService<TService>();
} }
public bool IntersectsWith(Location location)
{
if (location == null)
{
throw new ArgumentNullException(nameof(location));
}
return location.SourceTree == SyntaxTree && location.SourceSpan.IntersectsWith(Position);
}
} }
} }
...@@ -60,6 +60,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery ...@@ -60,6 +60,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Return syntaxTree.IsTypeContext(position, token, cancellationToken, semanticModelOpt) Return syntaxTree.IsTypeContext(position, token, cancellationToken, semanticModelOpt)
End Function End Function
<Extension()>
Public Function IsNamespaceDeclarationNameContext(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As Boolean
Dim statement = syntaxTree.GetTargetToken(position, cancellationToken).GetAncestor(Of NamespaceStatementSyntax)
Return statement IsNot Nothing AndAlso statement.Name.Span.IntersectsWith(position)
End Function
<Extension()> <Extension()>
Public Function GetContainingTypeBlock(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As TypeBlockSyntax Public Function GetContainingTypeBlock(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As TypeBlockSyntax
Dim token = syntaxTree.GetRoot(cancellationToken).FindToken(position) Dim token = syntaxTree.GetRoot(cancellationToken).FindToken(position)
......
...@@ -61,6 +61,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery ...@@ -61,6 +61,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
touchingToken As SyntaxToken, touchingToken As SyntaxToken,
isTypeContext As Boolean, isTypeContext As Boolean,
isNamespaceContext As Boolean, isNamespaceContext As Boolean,
isNamespaceDeclarationNameContext As Boolean,
isPreProcessorDirectiveContext As Boolean, isPreProcessorDirectiveContext As Boolean,
isRightOfNameSeparator As Boolean, isRightOfNameSeparator As Boolean,
isSingleLineStatementContext As Boolean, isSingleLineStatementContext As Boolean,
...@@ -83,6 +84,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery ...@@ -83,6 +84,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
targetToken, targetToken,
isTypeContext, isTypeContext,
isNamespaceContext, isNamespaceContext,
isNamespaceDeclarationNameContext,
isPreProcessorDirectiveContext, isPreProcessorDirectiveContext,
isRightOfNameSeparator, isRightOfNameSeparator,
isStatementContext:=isSingleLineStatementContext, isStatementContext:=isSingleLineStatementContext,
...@@ -141,6 +143,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery ...@@ -141,6 +143,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
touchingToken, touchingToken,
isTypeContext:=syntaxTree.IsTypeContext(position, targetToken, cancellationToken, semanticModel), isTypeContext:=syntaxTree.IsTypeContext(position, targetToken, cancellationToken, semanticModel),
isNamespaceContext:=syntaxTree.IsNamespaceContext(position, targetToken, cancellationToken, semanticModel), isNamespaceContext:=syntaxTree.IsNamespaceContext(position, targetToken, cancellationToken, semanticModel),
isNamespaceDeclarationNameContext:=syntaxTree.IsNamespaceDeclarationNameContext(position, cancellationToken),
isPreProcessorDirectiveContext:=syntaxTree.IsInPreprocessorDirectiveContext(position, cancellationToken), isPreProcessorDirectiveContext:=syntaxTree.IsInPreprocessorDirectiveContext(position, cancellationToken),
isRightOfNameSeparator:=syntaxTree.IsRightOfDot(position, cancellationToken), isRightOfNameSeparator:=syntaxTree.IsRightOfDot(position, cancellationToken),
isSingleLineStatementContext:=syntaxTree.IsSingleLineStatementContext(position, targetToken, cancellationToken), isSingleLineStatementContext:=syntaxTree.IsSingleLineStatementContext(position, targetToken, cancellationToken),
......
...@@ -245,10 +245,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -245,10 +245,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function End Function
Public Function IsNamespaceDeclarationNameContext(semanticModel As SemanticModel, position As Integer, cancellationToken As CancellationToken) As Boolean Implements ISemanticFactsService.IsNamespaceDeclarationNameContext Public Function IsNamespaceDeclarationNameContext(semanticModel As SemanticModel, position As Integer, cancellationToken As CancellationToken) As Boolean Implements ISemanticFactsService.IsNamespaceDeclarationNameContext
' Return semanticModel.SyntaxTree.IsNamespaceDeclarationNameContext(position, cancellationToken)
' TODO: part of https://github.com/dotnet/roslyn/issues/7213
'
Return False
End Function End Function
End Class End Class
End Namespace End Namespace
...@@ -4,7 +4,6 @@ Imports System.Collections.Immutable ...@@ -4,7 +4,6 @@ Imports System.Collections.Immutable
Imports System.Composition Imports System.Composition
Imports System.Threading Imports System.Threading
Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.LanguageServices
Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Recommendations Imports Microsoft.CodeAnalysis.Recommendations
Imports Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery Imports Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery
...@@ -72,11 +71,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations ...@@ -72,11 +71,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations
Dim symbols = GetUnqualifiedSymbolsForExpressionOrStatementContext(context, filterOutOfScopeLocals, cancellationToken) _ Dim symbols = GetUnqualifiedSymbolsForExpressionOrStatementContext(context, filterOutOfScopeLocals, cancellationToken) _
.Where(AddressOf IsWritableFieldOrLocal) .Where(AddressOf IsWritableFieldOrLocal)
Return symbols Return symbols
ElseIf context.IsNamespaceDeclarationNameContext Then
Return GetUnqualifiedSymbolsForNamespaceDeclarationNameContext(context, cancellationToken)
End If End If
Return SpecializedCollections.EmptyEnumerable(Of ISymbol)() Return SpecializedCollections.EmptyEnumerable(Of ISymbol)()
End Function End Function
Private Function GetUnqualifiedSymbolsForNamespaceDeclarationNameContext(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As IEnumerable(Of ISymbol)
Dim declarationSyntax = context.TargetToken.GetAncestor(Of NamespaceBlockSyntax)
Return GetRecommendedNamespaceNameSymbols(context.SemanticModel, declarationSyntax, cancellationToken)
End Function
Private Function IsWritableFieldOrLocal(symbol As ISymbol) As Boolean Private Function IsWritableFieldOrLocal(symbol As ISymbol) As Boolean
If symbol.Kind() = SymbolKind.Field Then If symbol.Kind() = SymbolKind.Field Then
Dim field = DirectCast(symbol, IFieldSymbol) Dim field = DirectCast(symbol, IFieldSymbol)
...@@ -170,7 +176,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations ...@@ -170,7 +176,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations
symbols = symbols.Where(Function(s) Not IsInEligibleDelegate(s)) symbols = symbols.Where(Function(s) Not IsInEligibleDelegate(s))
End If End If
' Hide backing fields and events ' Hide backing fields and events
Return symbols.Where(Function(s) FilterEventsAndGeneratedSymbols(Nothing, s)) Return symbols.Where(Function(s) FilterEventsAndGeneratedSymbols(Nothing, s))
End Function End Function
...@@ -190,11 +195,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations ...@@ -190,11 +195,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations
cancellationToken As CancellationToken cancellationToken As CancellationToken
) As IEnumerable(Of ISymbol) ) As IEnumerable(Of ISymbol)
' We shouldn't show completion if we're inside of a namespace statement.
If context.TargetToken.Parent.FirstAncestorOrSelf(Of NamespaceStatementSyntax)() IsNot Nothing Then
Return SpecializedCollections.EmptyEnumerable(Of ISymbol)()
End If
' We're in a name-only context, since if we were an expression we'd be a ' We're in a name-only context, since if we were an expression we'd be a
' MemberAccessExpressionSyntax. Thus, let's do other namespaces and types. ' MemberAccessExpressionSyntax. Thus, let's do other namespaces and types.
Dim leftHandSymbolInfo = context.SemanticModel.GetSymbolInfo(node.Left, cancellationToken) Dim leftHandSymbolInfo = context.SemanticModel.GetSymbolInfo(node.Left, cancellationToken)
...@@ -212,6 +212,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations ...@@ -212,6 +212,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations
Else Else
symbols = context.SemanticModel _ symbols = context.SemanticModel _
.LookupNamespacesAndTypes(position:=node.SpanStart, container:=leftHandSymbol) .LookupNamespacesAndTypes(position:=node.SpanStart, container:=leftHandSymbol)
If context.IsNamespaceDeclarationNameContext Then
Dim declarationSyntax = node.GetAncestor(Of NamespaceBlockSyntax)
symbols = symbols.Where(Function(symbol) IsNonIntersectingNamespace(symbol, declarationSyntax))
End If
End If End If
Return FilterToValidAccessibleSymbols(symbols, context, cancellationToken) Return FilterToValidAccessibleSymbols(symbols, context, cancellationToken)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册