提交 fc9b46fe 编写于 作者: J Jonathon Marolf 提交者: GitHub

Merge pull request #12092 from lorcanmooney/issue7213-partials

Add partial-type-name suggestions to C# and some fixes for VB
......@@ -939,6 +939,29 @@ public partial interface IFoo<T, V>
Assert.Equal("p1", psym.Name);
}
[Fact]
[WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
public void TestGetDeclaredSymbolWithIncompleteDeclaration()
{
var compilation = CreateCompilationWithMscorlib(@"
class C0 { }
class
class C1 { }
");
var tree = compilation.SyntaxTrees[0];
var root = tree.GetCompilationUnitRoot();
var typeDecl = (ClassDeclarationSyntax)root.Members[1];
var model = compilation.GetSemanticModel(tree);
var symbol = model.GetDeclaredSymbol(typeDecl);
Assert.NotNull(symbol);
Assert.Equal(string.Empty, symbol.ToTestDisplayString());
Assert.Equal(TypeKind.Class, symbol.TypeKind);
}
[WorkItem(537230, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537230")]
[Fact]
public void TestLookupUnresolvableNamespaceUsing()
......
......@@ -657,6 +657,9 @@ Microsoft.CodeAnalysis.Semantics.UnaryOperationKind.UnsignedPostfixDecrement = 7
Microsoft.CodeAnalysis.Semantics.UnaryOperationKind.UnsignedPostfixIncrement = 771 -> Microsoft.CodeAnalysis.Semantics.UnaryOperationKind
Microsoft.CodeAnalysis.Semantics.UnaryOperationKind.UnsignedPrefixDecrement = 774 -> Microsoft.CodeAnalysis.Semantics.UnaryOperationKind
Microsoft.CodeAnalysis.Semantics.UnaryOperationKind.UnsignedPrefixIncrement = 773 -> Microsoft.CodeAnalysis.Semantics.UnaryOperationKind
Microsoft.CodeAnalysis.SymbolDisplayFormat.RemoveGenericsOptions(Microsoft.CodeAnalysis.SymbolDisplayGenericsOptions options) -> Microsoft.CodeAnalysis.SymbolDisplayFormat
Microsoft.CodeAnalysis.SymbolDisplayFormat.RemoveLocalOptions(Microsoft.CodeAnalysis.SymbolDisplayLocalOptions options) -> Microsoft.CodeAnalysis.SymbolDisplayFormat
Microsoft.CodeAnalysis.SymbolDisplayFormat.RemoveMiscellaneousOptions(Microsoft.CodeAnalysis.SymbolDisplayMiscellaneousOptions options) -> Microsoft.CodeAnalysis.SymbolDisplayFormat
abstract Microsoft.CodeAnalysis.Diagnostics.OperationBlockStartAnalysisContext.RegisterOperationAction(System.Action<Microsoft.CodeAnalysis.Diagnostics.OperationAnalysisContext> action, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.OperationKind> operationKinds) -> void
abstract Microsoft.CodeAnalysis.Diagnostics.OperationBlockStartAnalysisContext.RegisterOperationBlockEndAction(System.Action<Microsoft.CodeAnalysis.Diagnostics.OperationBlockAnalysisContext> action) -> void
abstract Microsoft.CodeAnalysis.SemanticModel.GetOperationCore(Microsoft.CodeAnalysis.SyntaxNode node, System.Threading.CancellationToken cancellationToken) -> Microsoft.CodeAnalysis.IOperation
......
......@@ -436,6 +436,18 @@ public SymbolDisplayFormat AddMiscellaneousOptions(SymbolDisplayMiscellaneousOpt
return this.WithMiscellaneousOptions(this.MiscellaneousOptions | options);
}
/// <summary>
/// Creates a copy of the SymbolDisplayFormat without the specified <seealso cref="SymbolDisplayMiscellaneousOptions"/>.
/// </summary>
/// <param name="options">
/// An object specifying which parameters should not be applied to how miscellaneous symbols will be formatted.
/// </param>
/// <returns>A duplicate of the SymbolDisplayFormat, without the specified <seealso cref="SymbolDisplayMiscellaneousOptions"/>.</returns>
public SymbolDisplayFormat RemoveMiscellaneousOptions(SymbolDisplayMiscellaneousOptions options)
{
return this.WithMiscellaneousOptions(this.MiscellaneousOptions & ~options);
}
/// <summary>
/// Creates a copy of the SymbolDisplayFormat but with replaced set of <seealso cref="SymbolDisplayGenericsOptions"/>.
/// </summary>
......@@ -471,6 +483,20 @@ public SymbolDisplayFormat AddGenericsOptions(SymbolDisplayGenericsOptions optio
return this.WithGenericsOptions(this.GenericsOptions | options);
}
/// <summary>
/// Creates a copy of the SymbolDisplayFormat but with a set of <seealso cref="SymbolDisplayGenericsOptions"/> stripped away from the original object.
/// </summary>
/// <param name="options">
/// An object specifying which parameters should not be applied to how generic symbols will be formatted.
/// </param>
/// <returns>
/// A duplicate of the SymbolDisplayFormat, with a set of <seealso cref="SymbolDisplayGenericsOptions"/> stripped away from the original object.
/// </returns>
public SymbolDisplayFormat RemoveGenericsOptions(SymbolDisplayGenericsOptions options)
{
return this.WithGenericsOptions(this.GenericsOptions & ~options);
}
/// <summary>
/// Creates a copy of the SymbolDisplayFormat but with replaced set of <seealso cref="SymbolDisplayMemberOptions"/>.
/// </summary>
......@@ -673,17 +699,31 @@ public SymbolDisplayFormat WithLocalOptions(SymbolDisplayLocalOptions options)
}
/// <summary>
/// Creates a copy of the SymbolDisplayFormat but with an additional set of <seealso cref="SymbolDisplayParameterOptions"/>.
/// Creates a copy of the SymbolDisplayFormat but with an additional set of <seealso cref="SymbolDisplayLocalOptions"/>.
/// </summary>
/// <param name="options">
/// An object specifying additional parameters on how symbols belonging to locals should be formatted.
/// </param>
/// <returns>
/// A duplicate of the SymbolDisplayFormat, with an additional set of <seealso cref="SymbolDisplayParameterOptions"/>.
/// A duplicate of the SymbolDisplayFormat, with an additional set of <seealso cref="SymbolDisplayLocalOptions"/>.
/// </returns>
public SymbolDisplayFormat AddLocalOptions(SymbolDisplayLocalOptions options)
{
return this.WithLocalOptions(this.LocalOptions | options);
}
/// <summary>
/// Creates a copy of the SymbolDisplayFormat but with a set of <seealso cref="SymbolDisplayLocalOptions"/> stripped away from the original object.
/// </summary>
/// <param name="options">
/// An object specifying parameters that should not be applied when formatting symbols belonging to locals.
/// </param>
/// <returns>
/// A duplicate of the SymbolDisplayFormat, with a set of <seealso cref="SymbolDisplayLocalOptions"/> stripped away from the original object.
/// </returns>
public SymbolDisplayFormat RemoveLocalOptions(SymbolDisplayLocalOptions options)
{
return this.WithLocalOptions(this.LocalOptions & ~options);
}
}
}
......@@ -864,7 +864,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' </summary>
Private Function CheckSymbolLocationsAgainstSyntax(symbol As NamedTypeSymbol, nodeToCheck As VisualBasicSyntaxNode) As NamedTypeSymbol
For Each location In symbol.Locations
If location.SourceTree Is Me.SyntaxTree AndAlso nodeToCheck.Span.Contains(location.SourceSpan.Start) Then
If location.SourceTree Is Me.SyntaxTree AndAlso nodeToCheck.Span.Contains(location.SourceSpan) Then
Return symbol
End If
Next
......
......@@ -2933,6 +2933,30 @@ End Interface
Assert.NotNull(fSymbol2)
Assert.Equal("Function I1.F() As System.String", fSymbol2.ToTestDisplayString())
End Sub
<Fact(), WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")>
Public Sub TestGetDeclaredSymbolWithIncompleteDeclaration()
Dim compilation = CompilationUtils.CreateCompilationWithMscorlib(
<compilation name="Compilation">
<file name="a.vb">
Class C0
End Class
Class
Class C1
End Class
</file>
</compilation>)
Dim tree = compilation.SyntaxTrees(0)
Dim model = compilation.GetSemanticModel(tree)
Dim syntax = DirectCast(tree.FindNodeOrTokenByKind(SyntaxKind.ClassStatement, 2).AsNode(), ClassStatementSyntax)
Dim symbol = model.GetDeclaredSymbol(syntax)
Assert.NotNull(symbol)
Assert.Equal("?", symbol.ToTestDisplayString())
Assert.Equal(TypeKind.Class, symbol.TypeKind)
End Sub
#End Region
End Class
......
......@@ -186,7 +186,7 @@
<Compile Include="Completion\CompletionProviders\ObjectCreationCompletionProviderTests.cs" />
<Compile Include="Completion\CompletionProviders\ObjectInitializerCompletionProviderTests.cs" />
<Compile Include="Completion\CompletionProviders\OverrideCompletionProviderTests.cs" />
<Compile Include="Completion\CompletionProviders\PartialCompletionProviderTests.cs" />
<Compile Include="Completion\CompletionProviders\PartialMethodCompletionProviderTests.cs" />
<Compile Include="Completion\CompletionProviders\SnippetCompletionProviderTests.cs" />
<Compile Include="Completion\CompletionProviders\SpeculativeTCompletionProviderTests.cs" />
<Compile Include="Completion\CompletionProviders\SuggestionModeCompletionProviderTests.cs" />
......@@ -507,6 +507,7 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<SubType>Designer</SubType>
</None>
<Compile Include="Completion\CompletionProviders\PartialTypeCompletionProviderTests.cs" />
<Content Include="PerfTests\Sources\CSharpPgoTypingInput.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
......
......@@ -9,15 +9,15 @@
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders
{
public class PartialCompletionProviderTests : AbstractCSharpCompletionProviderTests
public class PartialMethodCompletionProviderTests : AbstractCSharpCompletionProviderTests
{
public PartialCompletionProviderTests(CSharpTestWorkspaceFixture workspaceFixture) : base(workspaceFixture)
public PartialMethodCompletionProviderTests(CSharpTestWorkspaceFixture workspaceFixture) : base(workspaceFixture)
{
}
internal override CompletionProvider CreateCompletionProvider()
{
return new PartialCompletionProvider();
return new PartialMethodCompletionProvider();
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......
// 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.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders
{
public class PartialTypeCompletionProviderTests : AbstractCSharpCompletionProviderTests
{
public PartialTypeCompletionProviderTests(CSharpTestWorkspaceFixture workspaceFixture) : base(workspaceFixture)
{
}
internal override CompletionProvider CreateCompletionProvider()
{
return new PartialTypeCompletionProvider();
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestRecommendTypesWithoutPartial()
{
var text = @"
class C { }
partial class $$";
await VerifyItemIsAbsentAsync(text, "C");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialClass1()
{
var text = @"
partial class C { }
partial class $$";
await VerifyItemExistsAsync(text, "C");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialGenericClass1()
{
var text = @"
class Bar { }
partial class C<Bar> { }
partial class $$";
await VerifyItemExistsAsync(text, "C<Bar>");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialGenericClassCommitOnParen()
{
var text = @"
class Bar { }
partial class C<Bar> { }
partial class $$";
var expected = @"
class Bar { }
partial class C<Bar> { }
partial class C<";
await VerifyProviderCommitAsync(text, "C<Bar>", expected, '<', "");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialGenericClassCommitOnTab()
{
var text = @"
class Bar { }
partial class C<Bar> { }
partial class $$";
var expected = @"
class Bar { }
partial class C<Bar> { }
partial class C<Bar>";
await VerifyProviderCommitAsync(text, "C<Bar>", expected, null, "");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialGenericClassCommitOnSpace()
{
var text = @"
partial class C<T> { }
partial class $$";
var expected = @"
partial class C<T> { }
partial class C<T> ";
await VerifyProviderCommitAsync(text, "C<T>", expected, ' ', "");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialClassWithModifiers()
{
var text = @"
partial class C { }
internal partial class $$";
await VerifyItemExistsAsync(text, "C");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialStruct()
{
var text = @"
partial struct S { }
partial struct $$";
await VerifyItemExistsAsync(text, "S");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialInterface()
{
var text = @"
partial interface I { }
partial interface $$";
await VerifyItemExistsAsync(text, "I");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestTypeKindMatches1()
{
var text = @"
partial struct S { }
partial class $$";
await VerifyNoItemsExistAsync(text);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestTypeKindMatches2()
{
var text = @"
partial class C { }
partial struct $$";
await VerifyNoItemsExistAsync(text);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialClassesInSameNamespace()
{
var text = @"
namespace N
{
partial class Foo { }
}
namespace N
{
partial class $$
}";
await VerifyItemExistsAsync(text, "Foo");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestNotPartialClassesAcrossDifferentNamespaces()
{
var text = @"
namespace N
{
partial class Foo { }
}
partial class $$";
await VerifyNoItemsExistAsync(text);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestNotPartialClassesInOuterNamespaces()
{
var text = @"
partial class C { }
namespace N
{
partial class $$
}
";
await VerifyNoItemsExistAsync(text);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestNotPartialClassesInOuterClass()
{
var text = @"
partial class C
{
partial class $$
}
";
await VerifyNoItemsExistAsync(text);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestClassWithConstraint()
{
var text = @"
partial class C1<T> where T : System.Exception { }
partial class $$";
var expected = @"
partial class C1<T> where T : System.Exception { }
partial class C1<T>";
await VerifyProviderCommitAsync(text, "C1<T>", expected, null, "");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestDoNotSuggestCurrentMember()
{
var text = @"partial class F$$";
await VerifyNoItemsExistAsync(text);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestNotInTrivia()
{
var text = @"
partial class C1 { }
partial class //$$";
await VerifyNoItemsExistAsync(text);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialClassWithReservedName()
{
var text = @"
partial class @class { }
partial class $$";
var expected = @"
partial class @class { }
partial class @class";
await VerifyProviderCommitAsync(text, "@class", expected, null, "");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialGenericClassWithReservedName()
{
var text = @"
partial class @class<T> { }
partial class $$";
var expected = @"
partial class @class<T> { }
partial class @class<T>";
await VerifyProviderCommitAsync(text, "@class<T>", expected, null, "");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TestPartialGenericInterfaceWithVariance()
{
var text = @"
partial interface I<out T> { }
partial interface $$";
var expected = @"
partial interface I<out T> { }
partial interface I<out T>";
await VerifyProviderCommitAsync(text, "I<out T>", expected, null, "");
}
}
}
\ No newline at end of file
......@@ -606,6 +606,30 @@ public async Task NamespaceDeclaration_Qualified()
await VerifyBuilderAsync(markup);
}
[WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task PartialClassName()
{
var markup = @"partial class $$";
await VerifyBuilderAsync(markup);
}
[WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task PartialStructName()
{
var markup = @"partial struct $$";
await VerifyBuilderAsync(markup);
}
[WorkItem(7213, "https://github.com/dotnet/roslyn/issues/7213")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task PartialInterfaceName()
{
var markup = @"partial interface $$";
await VerifyBuilderAsync(markup);
}
private async Task VerifyNotBuilderAsync(string markup)
{
await VerifyWorkerAsync(markup, isBuilder: false);
......
' 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.Threading.Tasks
Imports Microsoft.CodeAnalysis.Completion
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
......@@ -53,9 +52,6 @@ Partial Class $$</text>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestPartialGenericClassCommitOnParen() As Task
' TODO(DustinCa): This is testing the wrong behavior and will need to be updated to the commented expected
' result when https://github.com/dotnet/roslyn/issues/4137 is fixed.
Dim text = <text>Class Bar
End Class
......@@ -70,17 +66,22 @@ End Class
Partial Class C(Of Bar)
End Class
Partial Class C(Of Bar)(</text>
Partial Class C(</text>
' Dim expected = <text>Class Bar
'End Class
Await VerifyProviderCommitAsync(text.Value, "C(Of Bar)", expected.Value, "("c, "", SourceCodeKind.Regular)
End Function
'Partial Class C(Of Bar)
'End Class
<Fact(Skip:="https://github.com/dotnet/roslyn/issues/11569"), Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestPartialClassWithSameMemberName() As Task
Dim text = <text>Partial Class C(Of T)
Sub C()
End Sub
End Class
'Partial Class C(</text>
Partial Class $$C(Of T)
End Class</text>
Await VerifyProviderCommitAsync(text.Value, "C(Of Bar)", expected.Value, "("c, "", SourceCodeKind.Regular)
Await VerifyItemExistsAsync(text.Value, "C(Of T)")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
......@@ -104,12 +105,27 @@ Partial Class C(Of Bar)</text>
Await VerifyProviderCommitAsync(text.Value, "C(Of Bar)", expected.Value, Nothing, "", SourceCodeKind.Regular)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestPartialGenericClassCommitOnSpace() As Task
Dim text = <text>Partial Class C(Of T)
End Class
Partial Class $$</text>
Dim expected = <text>Partial Class C(Of T)
End Class
Partial Class C(Of T) </text>
Await VerifyProviderCommitAsync(text.Value, "C(Of T)", expected.Value, " "c, "", SourceCodeKind.Regular)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestPartialClassWithModifiers() As Task
Dim text = <text>Partial Class C
End Class
Partial Protected Class $$</text>
Partial Friend Class $$</text>
Await VerifyItemExistsAsync(text.Value, "C")
End Function
......@@ -193,6 +209,30 @@ Partial Class $$</text>
Await VerifyNoItemsExistAsync(text.Value)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestNotPartialClassesInOuterNamespaces() As Task
Dim text = <text>Partial Class C
End Class
Namespace N
Partial Class $$
End Namespace
</text>
Await VerifyNoItemsExistAsync(text.Value)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestNotPartialClassesInOuterClass() As Task
Dim text = <text>Partial Class C
Partial Class $$
End Class
</text>
Await VerifyNoItemsExistAsync(text.Value)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestIncludeConstraints() As Task
Dim text = <text>
......@@ -227,6 +267,66 @@ Partial Class '$$</text>
Await VerifyNoItemsExistAsync(text.Value)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestPartialClassWithReservedName() As Task
Dim text = <text>Partial Class [Class]
End Class
Partial Class $$</text>
Dim expected = <text>Partial Class [Class]
End Class
Partial Class [Class]</text>
Await VerifyProviderCommitAsync(text.Value, "Class", expected.Value, Nothing, "", SourceCodeKind.Regular)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestPartialGenericClassWithReservedName() As Task
Dim text = <text>Partial Class [Class](Of T)
End Class
Partial Class $$</text>
Dim expected = <text>Partial Class [Class](Of T)
End Class
Partial Class [Class](Of T)</text>
Await VerifyProviderCommitAsync(text.Value, "Class(Of T)", expected.Value, Nothing, "", SourceCodeKind.Regular)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestPartialGenericClassWithReservedNameCommittedWithParen() As Task
Dim text = <text>Partial Class [Class](Of T)
End Class
Partial Class $$</text>
Dim expected = <text>Partial Class [Class](Of T)
End Class
Partial Class [Class](</text>
Await VerifyProviderCommitAsync(text.Value, "Class(Of T)", expected.Value, "("c, "", SourceCodeKind.Regular)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestPartialGenericInterfaceWithVariance() As Task
Dim text = <text>Partial Interface G(Of Out T)
End Interface
Partial Interface $$</text>
Dim expected = <text>Partial Interface G(Of Out T)
End Interface
Partial Interface G(Of Out T)</text>
Await VerifyProviderCommitAsync(text.Value, "G(Of Out T)", expected.Value, Nothing, "", SourceCodeKind.Regular)
End Function
End Class
End Namespace
......@@ -308,7 +308,7 @@ End Class
Public Async Function NamespaceDeclarationName_Unqualified() As Task
Dim markup = <a>
Namespace $$
End Class
End Namespace
</a>
Await VerifyBuilderAsync(markup, CompletionTrigger.Default)
End Function
......@@ -318,11 +318,39 @@ End Class
Public Async Function NamespaceDeclarationName_Qualified() As Task
Dim markup = <a>
Namespace A.$$
End Class
End Namespace
</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 PartialClassName() As Task
Dim markup = <a>Partial 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 PartialStructureName() As Task
Dim markup = <a>Partial Structure $$</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 PartialInterfaceName() As Task
Dim markup = <a>Partial Interface $$</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 PartialModuleName() As Task
Dim markup = <a>Partial Module $$</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
Return VerifySuggestionModeWorkerAsync(markup, isBuilder:=False, triggerInfo:=triggerInfo, useDebuggerOptions:=useDebuggerOptions)
End Function
......
......@@ -566,8 +566,8 @@ End Class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)>
Public Async Function TestGenerateInDerivedType_Crash() As Task
Await TestMissingAsync(
Public Async Function TestGenerateInDerivedType_InvalidClassStatement() As Task
Await TestAsync(
"
Public Class Base
Public Sub New(a As Integer, Optional b As String = Nothing)
......@@ -578,6 +578,20 @@ End Class
Public Class [|;;|]Derived
Inherits Base
End Class",
"
Public Class Base
Public Sub New(a As Integer, Optional b As String = Nothing)
End Sub
End Class
Public Class ;;Derived
Inherits Base
Public Sub New(a As Integer, Optional b As String = Nothing)
MyBase.New(a, b)
End Sub
End Class")
End Function
......
......@@ -121,7 +121,8 @@
<Compile Include="Completion\CompletionProviders\ObjectCreationCompletionProvider.cs" />
<Compile Include="Completion\CompletionProviders\ObjectInitializerCompletionProvider.cs" />
<Compile Include="Completion\CompletionProviders\OverrideCompletionProvider.cs" />
<Compile Include="Completion\CompletionProviders\PartialCompletionProvider.cs" />
<Compile Include="Completion\CompletionProviders\PartialTypeCompletionProvider.cs" />
<Compile Include="Completion\CompletionProviders\PartialMethodCompletionProvider.cs" />
<Compile Include="Completion\CompletionProviders\SnippetCompletionProvider.cs" />
<Compile Include="Completion\CompletionProviders\SpeculativeTCompletionProvider.cs" />
<Compile Include="Completion\CompletionProviders\XmlDocCommentCompletionProvider.cs" />
......
......@@ -124,6 +124,15 @@ internal class CSharpFeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Autoselect disabled due to type declaration..
/// </summary>
internal static string AutoselectDisabledDueToTypeDeclaration {
get {
return ResourceManager.GetString("AutoselectDisabledDueToTypeDeclaration", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to awaitable.
/// </summary>
......@@ -205,6 +214,15 @@ internal class CSharpFeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to &lt;class name&gt;.
/// </summary>
internal static string ClassName {
get {
return ResourceManager.GetString("ClassName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Conflict(s) detected..
/// </summary>
......@@ -466,6 +484,15 @@ internal class CSharpFeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to &lt;interface name&gt;.
/// </summary>
internal static string InterfaceName {
get {
return ResourceManager.GetString("InterfaceName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to into clause.
/// </summary>
......@@ -862,6 +889,15 @@ internal class CSharpFeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to &lt;struct name&gt;.
/// </summary>
internal static string StructName {
get {
return ResourceManager.GetString("StructName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The selected code is inside an unsafe context..
/// </summary>
......
......@@ -452,4 +452,16 @@
<data name="NamespaceName" xml:space="preserve">
<value>&lt;namespace name&gt;</value>
</data>
<data name="AutoselectDisabledDueToTypeDeclaration" xml:space="preserve">
<value>Autoselect disabled due to type declaration.</value>
</data>
<data name="ClassName" xml:space="preserve">
<value>&lt;class name&gt;</value>
</data>
<data name="InterfaceName" xml:space="preserve">
<value>&lt;interface name&gt;</value>
</data>
<data name="StructName" xml:space="preserve">
<value>&lt;struct name&gt;</value>
</data>
</root>
\ No newline at end of file
......@@ -39,7 +39,8 @@ internal class CSharpCompletionService : CommonCompletionService
new SnippetCompletionProvider(),
new ExternAliasCompletionProvider(),
new OverrideCompletionProvider(),
new PartialCompletionProvider(),
new PartialMethodCompletionProvider(),
new PartialTypeCompletionProvider(),
new XmlDocCommentCompletionProvider()
);
......
......@@ -16,9 +16,9 @@
namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers
{
internal partial class PartialCompletionProvider : AbstractPartialCompletionProvider
internal partial class PartialMethodCompletionProvider : AbstractPartialMethodCompletionProvider
{
public PartialCompletionProvider()
public PartialMethodCompletionProvider()
{
}
......@@ -50,29 +50,29 @@ internal override bool IsInsertionTrigger(SourceText text, int characterPosition
return ch == ' ' || (CompletionUtilities.IsStartingNewWord(text, characterPosition) && options.GetOption(CompletionOptions.TriggerOnTypingLetters, LanguageNames.CSharp));
}
protected override bool IsPartial(IMethodSymbol m)
protected override bool IsPartial(IMethodSymbol method)
{
if (m.DeclaredAccessibility != Accessibility.NotApplicable &&
m.DeclaredAccessibility != Accessibility.Private)
if (method.DeclaredAccessibility != Accessibility.NotApplicable &&
method.DeclaredAccessibility != Accessibility.Private)
{
return false;
}
if (!m.ReturnsVoid)
if (!method.ReturnsVoid)
{
return false;
}
if (m.IsVirtual)
if (method.IsVirtual)
{
return false;
}
var declarations = m.DeclaringSyntaxReferences.Select(r => r.GetSyntax()).OfType<MethodDeclarationSyntax>();
var declarations = method.DeclaringSyntaxReferences.Select(r => r.GetSyntax()).OfType<MethodDeclarationSyntax>();
return declarations.Any(d => d.Body == null && d.Modifiers.Any(SyntaxKind.PartialKeyword));
}
protected override bool IsPartialCompletionContext(SyntaxTree tree, int position, CancellationToken cancellationToken, out DeclarationModifiers modifiers, out SyntaxToken token)
protected override bool IsPartialMethodCompletionContext(SyntaxTree tree, int position, CancellationToken cancellationToken, out DeclarationModifiers modifiers, out SyntaxToken token)
{
var touchingToken = tree.FindTokenOnLeftOfPosition(position, cancellationToken);
var targetToken = touchingToken.GetPreviousTokenIfTouchingWord(position);
......
// 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.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Completion.Providers;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers
{
internal partial class PartialTypeCompletionProvider : AbstractPartialTypeCompletionProvider
{
private static readonly SymbolDisplayFormat _symbolFormatWithGenerics =
new SymbolDisplayFormat(
globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted,
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameOnly,
genericsOptions:
SymbolDisplayGenericsOptions.IncludeTypeParameters |
SymbolDisplayGenericsOptions.IncludeVariance,
miscellaneousOptions:
SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
private static readonly SymbolDisplayFormat _symbolFormatWithoutGenerics =
_symbolFormatWithGenerics.WithGenericsOptions(SymbolDisplayGenericsOptions.None);
internal override bool IsInsertionTrigger(SourceText text, int characterPosition, OptionSet options)
{
var ch = text[characterPosition];
return ch == ' ' ||
(CompletionUtilities.IsStartingNewWord(text, characterPosition) &&
options.GetOption(CompletionOptions.TriggerOnTypingLetters, LanguageNames.CSharp));
}
protected override SyntaxNode GetPartialTypeSyntaxNode(SyntaxTree tree, int position, CancellationToken cancellationToken)
{
TypeDeclarationSyntax declaration;
return tree.IsPartialTypeDeclarationNameContext(position, cancellationToken, out declaration) ? declaration : null;
}
protected override Task<AbstractSyntaxContext> CreateSyntaxContextAsync(Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken)
{
return Task.FromResult<AbstractSyntaxContext>(CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken));
}
protected override ValueTuple<string, string> GetDisplayAndInsertionText(INamedTypeSymbol symbol, AbstractSyntaxContext context)
{
var displayAndInsertionText = symbol.ToMinimalDisplayString(context.SemanticModel, context.Position, _symbolFormatWithGenerics);
return ValueTuple.Create(displayAndInsertionText, displayAndInsertionText);
}
protected override IEnumerable<INamedTypeSymbol> LookupCandidateSymbols(AbstractSyntaxContext context, INamedTypeSymbol declaredSymbol, CancellationToken cancellationToken)
{
var candidates = base.LookupCandidateSymbols(context, declaredSymbol, cancellationToken);
// The base class applies a broad filter when finding candidates, but since C# requires
// that all parts have the "partial" modifier, the results can be trimmed further here.
return candidates?.Where(symbol => symbol.DeclaringSyntaxReferences.Any(reference => IsPartialTypeDeclaration(reference.GetSyntax(cancellationToken))));
}
private static bool IsPartialTypeDeclaration(SyntaxNode syntax)
{
var declarationSyntax = syntax as BaseTypeDeclarationSyntax;
return declarationSyntax != null && declarationSyntax.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.PartialKeyword));
}
public async override Task<TextChange?> GetTextChangeAsync(Document document, CompletionItem selectedItem, char? ch, CancellationToken cancellationToken)
{
if (ch == '<')
{
var symbols = await SymbolCompletionItem.GetSymbolsAsync(selectedItem, document, cancellationToken).ConfigureAwait(false);
if (symbols.Length > 0)
{
var insertionText = symbols[0].Name.EscapeIdentifier();
return new TextChange(selectedItem.Span, insertionText);
}
}
return await base.GetTextChangeAsync(document, selectedItem, ch, cancellationToken).ConfigureAwait(false);
}
}
}
// 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.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Completion.SuggestionMode;
using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.CSharp.Symbols;
......@@ -40,6 +38,8 @@ internal class CSharpSuggestionModeCompletionProvider : SuggestionModeCompletion
var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false);
var typeInferrer = document.GetLanguageService<ITypeInferenceService>();
TypeDeclarationSyntax typeDeclaration;
if (IsLambdaExpression(semanticModel, position, token, typeInferrer, cancellationToken))
{
return CreateSuggestionModeItem(CSharpFeaturesResources.LambdaExpression, CSharpFeaturesResources.AutoselectDisabledDueToPotentialLambdaDeclaration);
......@@ -64,6 +64,20 @@ internal class CSharpSuggestionModeCompletionProvider : SuggestionModeCompletion
{
return CreateSuggestionModeItem(CSharpFeaturesResources.NamespaceName, CSharpFeaturesResources.AutoselectDisabledDueToNamespaceDeclaration);
}
else if (tree.IsPartialTypeDeclarationNameContext(position, cancellationToken, out typeDeclaration))
{
switch (typeDeclaration.Keyword.Kind())
{
case SyntaxKind.ClassKeyword:
return CreateSuggestionModeItem(CSharpFeaturesResources.ClassName, CSharpFeaturesResources.AutoselectDisabledDueToTypeDeclaration);
case SyntaxKind.StructKeyword:
return CreateSuggestionModeItem(CSharpFeaturesResources.StructName, CSharpFeaturesResources.AutoselectDisabledDueToTypeDeclaration);
case SyntaxKind.InterfaceKeyword:
return CreateSuggestionModeItem(CSharpFeaturesResources.InterfaceName, CSharpFeaturesResources.AutoselectDisabledDueToTypeDeclaration);
}
}
}
return null;
......
......@@ -8,11 +8,10 @@
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Completion.Providers
{
internal abstract partial class AbstractPartialCompletionProvider : AbstractMemberInsertingCompletionProvider
internal abstract partial class AbstractPartialMethodCompletionProvider : AbstractMemberInsertingCompletionProvider
{
protected static readonly SymbolDisplayFormat SignatureDisplayFormat =
new SymbolDisplayFormat(
......@@ -27,13 +26,13 @@ internal abstract partial class AbstractPartialCompletionProvider : AbstractMemb
SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
public AbstractPartialCompletionProvider()
protected AbstractPartialMethodCompletionProvider()
{
}
protected abstract bool IsPartialCompletionContext(SyntaxTree tree, int position, CancellationToken cancellationToken, out DeclarationModifiers modifiers, out SyntaxToken token);
protected abstract bool IsPartialMethodCompletionContext(SyntaxTree tree, int position, CancellationToken cancellationToken, out DeclarationModifiers modifiers, out SyntaxToken token);
protected abstract string GetDisplayText(IMethodSymbol method, SemanticModel semanticModel, int position);
protected abstract bool IsPartial(IMethodSymbol m);
protected abstract bool IsPartial(IMethodSymbol method);
public override async Task ProvideCompletionsAsync(CompletionContext context)
{
......@@ -45,7 +44,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
DeclarationModifiers modifiers;
SyntaxToken token;
if (!IsPartialCompletionContext(tree, position, cancellationToken, out modifiers, out token))
if (!IsPartialMethodCompletionContext(tree, position, cancellationToken, out modifiers, out token))
{
return;
}
......
// 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.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Completion.Providers
{
internal abstract partial class AbstractPartialTypeCompletionProvider : CommonCompletionProvider
{
protected AbstractPartialTypeCompletionProvider()
{
}
public async sealed override Task ProvideCompletionsAsync(CompletionContext completionContext)
{
var document = completionContext.Document;
var position = completionContext.Position;
var cancellationToken = completionContext.CancellationToken;
var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
var node = GetPartialTypeSyntaxNode(tree, position, cancellationToken);
if (node != null)
{
var semanticModel = await document.GetSemanticModelForNodeAsync(node, cancellationToken).ConfigureAwait(false);
var syntaxContext = await CreateSyntaxContextAsync(document, semanticModel, position, cancellationToken).ConfigureAwait(false);
var declaredSymbol = semanticModel.GetDeclaredSymbol(node, cancellationToken) as INamedTypeSymbol;
if (declaredSymbol != null)
{
var symbols = LookupCandidateSymbols(syntaxContext, declaredSymbol, cancellationToken);
var items = symbols?.Select(symbol => CreateCompletionItem(symbol, completionContext.CompletionListSpan, position, syntaxContext));
if (items != null)
{
completionContext.AddItems(items);
}
}
}
}
private CompletionItem CreateCompletionItem(INamedTypeSymbol symbol, TextSpan textSpan, int position, AbstractSyntaxContext context)
{
var displayAndInsertionText = GetDisplayAndInsertionText(symbol, context);
return SymbolCompletionItem.Create(
displayText: displayAndInsertionText.Item1,
insertionText: displayAndInsertionText.Item2,
symbol: symbol,
contextPosition: context.Position,
descriptionPosition: position,
rules: CompletionItemRules.Default);
}
protected abstract Task<AbstractSyntaxContext> CreateSyntaxContextAsync(
Document document,
SemanticModel semanticModel,
int position,
CancellationToken cancellationToken);
protected abstract SyntaxNode GetPartialTypeSyntaxNode(SyntaxTree tree, int position, CancellationToken cancellationToken);
protected abstract ValueTuple<string, string> GetDisplayAndInsertionText(INamedTypeSymbol symbol, AbstractSyntaxContext context);
protected virtual IEnumerable<INamedTypeSymbol> LookupCandidateSymbols(AbstractSyntaxContext context, INamedTypeSymbol declaredSymbol, CancellationToken cancellationToken)
{
if (declaredSymbol == null)
{
throw new ArgumentNullException(nameof(declaredSymbol));
}
SemanticModel semanticModel = context.SemanticModel;
INamespaceOrTypeSymbol containingSymbol = declaredSymbol.ContainingSymbol as INamespaceOrTypeSymbol;
if (containingSymbol == null)
{
return SpecializedCollections.EmptyEnumerable<INamedTypeSymbol>();
}
return semanticModel.LookupNamespacesAndTypes(context.Position, containingSymbol)
.OfType<INamedTypeSymbol>()
.Where(symbol => declaredSymbol.TypeKind == symbol.TypeKind &&
NotNewDeclaredMember(symbol, context) &&
InSameProject(symbol, semanticModel.Compilation));
}
private static bool InSameProject(INamedTypeSymbol symbol, Compilation compilation)
{
return symbol.DeclaringSyntaxReferences.Any(r => compilation.SyntaxTrees.Contains(r.SyntaxTree));
}
private static bool NotNewDeclaredMember(INamedTypeSymbol symbol, AbstractSyntaxContext context)
{
return symbol.DeclaringSyntaxReferences
.Select(reference => reference.GetSyntax())
.Any(node => !(node.SyntaxTree == context.SyntaxTree && node.Span.IntersectsWith(context.Position)));
}
public override Task<CompletionDescription> GetDescriptionAsync(Document document, CompletionItem item, CancellationToken cancellationToken)
{
return SymbolCompletionItem.GetDescriptionAsync(item, document, cancellationToken);
}
public override Task<TextChange?> GetTextChangeAsync(Document document, CompletionItem selectedItem, char? ch, CancellationToken cancellationToken)
{
var insertionText = SymbolCompletionItem.GetInsertionText(selectedItem);
return Task.FromResult<TextChange?>(new TextChange(selectedItem.Span, insertionText));
}
}
}
......@@ -187,7 +187,8 @@
<Compile Include="Completion\Providers\AbstractMemberInsertingCompletionProvider.cs" />
<Compile Include="Completion\Providers\AbstractOverrideCompletionProvider.cs" />
<Compile Include="Completion\Providers\AbstractOverrideCompletionProvider.ItemGetter.cs" />
<Compile Include="Completion\Providers\AbstractPartialCompletionProvider.cs" />
<Compile Include="Completion\Providers\AbstractPartialTypeCompletionProvider.cs" />
<Compile Include="Completion\Providers\AbstractPartialMethodCompletionProvider.cs" />
<Compile Include="Completion\ExportCompletionProviderAttribute.cs" />
<Compile Include="Completion\CompletionService.cs" />
<Compile Include="Completion\Providers\MemberInsertingCompletionItem.cs" />
......
' 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.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Completion
Imports Microsoft.CodeAnalysis.Completion.Providers
Imports Microsoft.CodeAnalysis.LanguageServices
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Partial Friend Class PartialTypeCompletionProvider
Inherits CommonCompletionProvider
Inherits AbstractPartialTypeCompletionProvider
Private ReadOnly _partialNameFormat As SymbolDisplayFormat =
Private Shared ReadOnly _insertionTextFormatWithGenerics As SymbolDisplayFormat =
New SymbolDisplayFormat(
globalNamespaceStyle:=SymbolDisplayGlobalNamespaceStyle.Omitted,
typeQualificationStyle:=SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
propertyStyle:=SymbolDisplayPropertyStyle.NameOnly,
genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters Or SymbolDisplayGenericsOptions.IncludeVariance Or
SymbolDisplayGenericsOptions.IncludeTypeConstraints,
miscellaneousOptions:=
SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers Or
SymbolDisplayMiscellaneousOptions.UseSpecialTypes)
SymbolDisplayMiscellaneousOptions.UseSpecialTypes,
genericsOptions:=
SymbolDisplayGenericsOptions.IncludeTypeParameters Or
SymbolDisplayGenericsOptions.IncludeVariance Or
SymbolDisplayGenericsOptions.IncludeTypeConstraints)
Friend Overrides Function IsInsertionTrigger(text As SourceText, characterPosition As Integer, options As OptionSet) As Boolean
Return CompletionUtilities.IsDefaultTriggerCharacter(text, characterPosition, options)
End Function
Public Overrides Async Function ProvideCompletionsAsync(context As CompletionContext) As Task
Dim document = context.Document
Dim position = context.Position
Dim cancellationToken = context.CancellationToken
Private Shared ReadOnly _insertionTextFormatWithoutGenerics As SymbolDisplayFormat =
_insertionTextFormatWithGenerics.WithGenericsOptions(SymbolDisplayGenericsOptions.None)
Dim tree = Await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(False)
If tree.IsInNonUserCode(position, cancellationToken) OrElse tree.IsInSkippedText(position, cancellationToken) Then
Return
End If
Dim token = tree.FindTokenOnLeftOfPosition(position, cancellationToken).GetPreviousTokenIfTouchingWord(position)
If token.IsChildToken(Of ClassStatementSyntax)(Function(stmt) stmt.DeclarationKeyword) OrElse
token.IsChildToken(Of StructureStatementSyntax)(Function(stmt) stmt.DeclarationKeyword) OrElse
token.IsChildToken(Of InterfaceStatementSyntax)(Function(stmt) stmt.DeclarationKeyword) OrElse
token.IsChildToken(Of ModuleStatementSyntax)(Function(stmt) stmt.DeclarationKeyword) Then
Private Shared ReadOnly _displayTextFormat As SymbolDisplayFormat =
_insertionTextFormatWithGenerics.RemoveMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers)
If token.GetAncestor(Of TypeStatementSyntax).Modifiers.Any(SyntaxKind.PartialKeyword) Then
Dim items = Await CreateItemsAsync(document, position, context.CompletionListSpan, token, cancellationToken).ConfigureAwait(False)
If items?.Any() Then
context.AddItems(items)
End If
End If
End If
Friend Overrides Function IsInsertionTrigger(text As SourceText, characterPosition As Integer, options As OptionSet) As Boolean
Return CompletionUtilities.IsDefaultTriggerCharacter(text, characterPosition, options)
End Function
Private Async Function CreateItemsAsync(document As Document, position As Integer, span As TextSpan, token As SyntaxToken, cancellationToken As CancellationToken) As Task(Of IEnumerable(Of CompletionItem))
Dim semanticModel = Await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(False)
' Unless the enclosing symbol is already the global namespace, we want to get it's enclosing symbol
' in order to suggest partial types in our namespace.
Dim enclosingSymbol = semanticModel.GetEnclosingSymbol(position, cancellationToken)
Dim enclosingNamespace = TryCast(enclosingSymbol, INamespaceSymbol)
If Not (enclosingNamespace IsNot Nothing AndAlso enclosingNamespace.IsGlobalNamespace) Then
enclosingSymbol = enclosingSymbol.ContainingSymbol
End If
Dim displayService = document.GetLanguageService(Of ISymbolDisplayService)()
Dim text = Await document.GetTextAsync(cancellationToken).ConfigureAwait(False)
Dim compilation = semanticModel.Compilation
Dim context = Await VisualBasicSyntaxContext.CreateContextAsync(document.Project.Solution.Workspace, semanticModel, position, cancellationToken).ConfigureAwait(False)
Return semanticModel.LookupNamespacesAndTypes(position) _
.OfType(Of INamedTypeSymbol)() _
.Where(Function(s) NotNewDeclaredMember(s, token)) _
.Where(Function(s) MatchesTypeKind(s, token) AndAlso InSameProject(s, compilation)) _
.Select(Function(s) CreateCompletionItem(s, displayService, token.SpanStart, context))
Protected Overrides Function GetPartialTypeSyntaxNode(tree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As SyntaxNode
Dim statement As TypeStatementSyntax = Nothing
Return If(tree.IsPartialTypeDeclarationNameContext(position, cancellationToken, statement), statement, Nothing)
End Function
Private Function MatchesTypeKind(symbol As INamedTypeSymbol, token As SyntaxToken) As Boolean
Select Case token.Kind
Case SyntaxKind.ClassKeyword
Return symbol.TypeKind = TypeKind.Class
Case SyntaxKind.StructureKeyword
Return symbol.TypeKind = TypeKind.Struct
Case SyntaxKind.ModuleKeyword
Return symbol.TypeKind = TypeKind.Module
Case SyntaxKind.InterfaceKeyword
Return symbol.TypeKind = TypeKind.Interface
Case Else
Return False
End Select
Protected Overrides Async Function CreateSyntaxContextAsync(document As Document, semanticModel As SemanticModel, position As Integer, cancellationToken As CancellationToken) As Task(Of AbstractSyntaxContext)
Return Await VisualBasicSyntaxContext.CreateContextAsync(document.Project.Solution.Workspace, semanticModel, position, cancellationToken).ConfigureAwait(False)
End Function
Private Function InSameProject(symbol As INamedTypeSymbol, compilation As Compilation) As Boolean
Return symbol.DeclaringSyntaxReferences.Any(Function(r) compilation.SyntaxTrees.Contains(r.SyntaxTree))
Protected Overrides Function GetDisplayAndInsertionText(symbol As INamedTypeSymbol, context As AbstractSyntaxContext) As ValueTuple(Of String, String)
Dim displayText = symbol.ToMinimalDisplayString(context.SemanticModel, context.Position, format:=_displayTextFormat)
Dim insertionText = symbol.ToMinimalDisplayString(context.SemanticModel, context.Position, format:=_insertionTextFormatWithGenerics)
Return ValueTuple.Create(displayText, insertionText)
End Function
Private Function CreateCompletionItem(symbol As INamedTypeSymbol,
displayService As ISymbolDisplayService,
position As Integer,
context As VisualBasicSyntaxContext) As CompletionItem
Dim displayText As String = Nothing
Dim insertionText As String = Nothing
If symbol.MatchesKind(SymbolKind.NamedType) AndAlso symbol.GetArity() > 0 Then
displayText = symbol.ToMinimalDisplayString(context.SemanticModel, position, format:=_partialNameFormat)
insertionText = displayText
Else
Dim displayAndInsertionText = CompletionUtilities.GetDisplayAndInsertionText(symbol, isAttributeNameContext:=False, isAfterDot:=False, isWithinAsyncMethod:=False, syntaxFacts:=context.GetLanguageService(Of ISyntaxFactsService))
displayText = displayAndInsertionText.Item1
insertionText = displayAndInsertionText.Item2
Public Overrides Async Function GetTextChangeAsync(document As Document, selectedItem As CompletionItem, ch As Char?, cancellationToken As CancellationToken) As Task(Of TextChange?)
If ch = "("c Then
Dim symbols = Await SymbolCompletionItem.GetSymbolsAsync(selectedItem, document, cancellationToken).ConfigureAwait(False)
If symbols.Length > 0 Then
Dim position = SymbolCompletionItem.GetContextPosition(selectedItem)
Dim semanticModel = Await document.GetSemanticModelForSpanAsync(New TextSpan(position, 0), cancellationToken).ConfigureAwait(False)
Dim insertionText = symbols(0).ToMinimalDisplayString(semanticModel, position, format:=_insertionTextFormatWithoutGenerics)
Return New TextChange(selectedItem.Span, insertionText)
End If
End If
Return SymbolCompletionItem.Create(
displayText:=displayText,
insertionText:=insertionText,
symbol:=symbol,
contextPosition:=context.Position,
descriptionPosition:=position,
rules:=CompletionItemRules.Default)
End Function
Public Overrides Function GetDescriptionAsync(document As Document, item As CompletionItem, cancellationToken As CancellationToken) As Task(Of CompletionDescription)
Return SymbolCompletionItem.GetDescriptionAsync(item, document, cancellationToken)
Return Await MyBase.GetTextChangeAsync(document, selectedItem, ch, cancellationToken).ConfigureAwait(False)
End Function
Private Function NotNewDeclaredMember(s As INamedTypeSymbol, token As SyntaxToken) As Boolean
Return Not s.DeclaringSyntaxReferences.Select(Function(r) r.GetSyntax()).All(Function(a) a.Span.IntersectsWith(token.Span))
End Function
Protected Overrides Function GetTextChangeAsync(selectedItem As CompletionItem, ch As Char?, cancellationToken As CancellationToken) As Task(Of TextChange?)
Dim insertionText = SymbolCompletionItem.GetInsertionText(selectedItem)
Return Task.FromResult(Of TextChange?)(New TextChange(selectedItem.Span, insertionText))
End Function
End Class
End Namespace
\ No newline at end of file
......@@ -97,11 +97,45 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.SuggestionMode
If syntaxTree.IsNamespaceDeclarationNameContext(position, cancellationToken) Then
description = VBFeaturesResources.TypeANameHereToDeclareANamespace & vbCrLf &
VBFeaturesResources.NoteSpaceAndCompletion
VBFeaturesResources.NoteSpaceCompletionIsDisa
Return CreateSuggestionModeItem(VBFeaturesResources.NamespaceName, description)
End If
Dim statementSyntax As TypeStatementSyntax = Nothing
' Builder after Partial (Class|Structure|Interface|Module)
If syntaxTree.IsPartialTypeDeclarationNameContext(position, cancellationToken, statementSyntax) Then
Select Case statementSyntax.DeclarationKeyword.Kind()
Case SyntaxKind.ClassKeyword
Return CreateSuggestionModeItem(
VBFeaturesResources.ClassName,
VBFeaturesResources.TypeANameHereToDeclareAPartialClass & vbCrLf &
VBFeaturesResources.NoteSpaceCompletionIsDisa)
Case SyntaxKind.InterfaceKeyword
Return CreateSuggestionModeItem(
VBFeaturesResources.InterfaceName,
VBFeaturesResources.TypeANameHereToDeclareAPartialInterface & vbCrLf &
VBFeaturesResources.NoteSpaceCompletionIsDisa)
Case SyntaxKind.StructureKeyword
Return CreateSuggestionModeItem(
VBFeaturesResources.StructureName,
VBFeaturesResources.TypeANameHereToDeclareAPartialStructure & vbCrLf &
VBFeaturesResources.NoteSpaceCompletionIsDisa)
Case SyntaxKind.ModuleKeyword
Return CreateSuggestionModeItem(
VBFeaturesResources.ModuleName,
VBFeaturesResources.TypeANameHereToDeclareAPartialModule & vbCrLf &
VBFeaturesResources.NoteSpaceCompletionIsDisa)
End Select
End If
Return Nothing
End Function
......
......@@ -391,6 +391,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources
End Get
End Property
'''<summary>
''' Looks up a localized string similar to &lt;class name&gt;.
'''</summary>
Friend ReadOnly Property ClassName() As String
Get
Return ResourceManager.GetString("ClassName", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Sets the default comparison method to use when comparing string data. When set to Text, uses a text sort order that is not case sensitive. When set to Binary, uses a strict binary sort order.
'''Option Compare {Binary | Text}.
......@@ -1489,6 +1498,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources
End Get
End Property
'''<summary>
''' Looks up a localized string similar to &lt;interface name&gt;.
'''</summary>
Friend ReadOnly Property InterfaceName() As String
Get
Return ResourceManager.GetString("InterfaceName", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Specifies an identifier that can serve as a reference to the results of a join or grouping subexpression..
'''</summary>
......@@ -1784,6 +1802,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources
End Get
End Property
'''<summary>
''' Looks up a localized string similar to &lt;module name&gt;.
'''</summary>
Friend ReadOnly Property ModuleName() As String
Get
Return ResourceManager.GetString("ModuleName", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to module.
'''</summary>
......@@ -2703,6 +2730,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources
End Get
End Property
'''<summary>
''' Looks up a localized string similar to &lt;structure name&gt;.
'''</summary>
Friend ReadOnly Property StructureName() As String
Get
Return ResourceManager.GetString("StructureName", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to structure.
'''</summary>
......@@ -2895,6 +2931,42 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Type a name here to declare a partial class..
'''</summary>
Friend ReadOnly Property TypeANameHereToDeclareAPartialClass() As String
Get
Return ResourceManager.GetString("TypeANameHereToDeclareAPartialClass", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Type a name here to declare a partial interface..
'''</summary>
Friend ReadOnly Property TypeANameHereToDeclareAPartialInterface() As String
Get
Return ResourceManager.GetString("TypeANameHereToDeclareAPartialInterface", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Type a name here to declare a partial module..
'''</summary>
Friend ReadOnly Property TypeANameHereToDeclareAPartialModule() As String
Get
Return ResourceManager.GetString("TypeANameHereToDeclareAPartialModule", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Type a name here to declare a partial structure..
'''</summary>
Friend ReadOnly Property TypeANameHereToDeclareAPartialStructure() As String
Get
Return ResourceManager.GetString("TypeANameHereToDeclareAPartialStructure", resourceCulture)
End Get
End Property
'''<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..
'''</summary>
......
......@@ -1198,4 +1198,28 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</value>
<data name="TypeANameHereToDeclareANamespace" xml:space="preserve">
<value>Type a name here to declare a namespace.</value>
</data>
<data name="TypeANameHereToDeclareAPartialClass" xml:space="preserve">
<value>Type a name here to declare a partial class.</value>
</data>
<data name="ClassName" xml:space="preserve">
<value>&lt;class name&gt;</value>
</data>
<data name="InterfaceName" xml:space="preserve">
<value>&lt;interface name&gt;</value>
</data>
<data name="ModuleName" xml:space="preserve">
<value>&lt;module name&gt;</value>
</data>
<data name="StructureName" xml:space="preserve">
<value>&lt;structure name&gt;</value>
</data>
<data name="TypeANameHereToDeclareAPartialInterface" xml:space="preserve">
<value>Type a name here to declare a partial interface.</value>
</data>
<data name="TypeANameHereToDeclareAPartialModule" xml:space="preserve">
<value>Type a name here to declare a partial module.</value>
</data>
<data name="TypeANameHereToDeclareAPartialStructure" xml:space="preserve">
<value>Type a name here to declare a partial structure.</value>
</data>
</root>
\ No newline at end of file
......@@ -618,6 +618,27 @@ public static bool IsNamespaceDeclarationNameContext(this SyntaxTree syntaxTree,
return declaration != null && (declaration.Name.Span.IntersectsWith(position) || declaration.NamespaceKeyword == token);
}
public static bool IsPartialTypeDeclarationNameContext(this SyntaxTree syntaxTree, int position, CancellationToken cancellationToken, out TypeDeclarationSyntax declarationSyntax)
{
if (!syntaxTree.IsInNonUserCode(position, cancellationToken))
{
var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken)
.GetPreviousTokenIfTouchingWord(position);
if ((token.IsKind(SyntaxKind.ClassKeyword) ||
token.IsKind(SyntaxKind.StructKeyword) ||
token.IsKind(SyntaxKind.InterfaceKeyword)) &&
token.GetPreviousToken().IsKind(SyntaxKind.PartialKeyword))
{
declarationSyntax = token.GetAncestor<TypeDeclarationSyntax>();
return declarationSyntax != null && declarationSyntax.Keyword == token;
}
}
declarationSyntax = null;
return false;
}
public static bool IsDefinitelyNotTypeContext(this SyntaxTree syntaxTree, int position, CancellationToken cancellationToken)
{
return
......
......@@ -74,6 +74,30 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Return statement IsNot Nothing AndAlso (statement.Name.Span.IntersectsWith(position) OrElse statement.NamespaceKeyword = token)
End Function
<Extension()>
Public Function IsPartialTypeDeclarationNameContext(tree As SyntaxTree, position As Integer, cancellationToken As CancellationToken, ByRef statementSyntax As TypeStatementSyntax) As Boolean
If tree.IsInNonUserCode(position, cancellationToken) OrElse tree.IsInSkippedText(position, cancellationToken) Then
Return False
End If
Dim token = tree.FindTokenOnLeftOfPosition(position, cancellationToken) _
.GetPreviousTokenIfTouchingWord(position)
Select Case token.Kind()
Case SyntaxKind.ClassKeyword,
SyntaxKind.StructureKeyword,
SyntaxKind.InterfaceKeyword,
SyntaxKind.ModuleKeyword
statementSyntax = token.GetAncestor(Of TypeStatementSyntax)()
Return statementSyntax IsNot Nothing AndAlso
statementSyntax.DeclarationKeyword = token AndAlso
statementSyntax.Modifiers.Any(SyntaxKind.PartialKeyword)
End Select
Return False
End Function
<Extension()>
Public Function GetContainingTypeBlock(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As TypeBlockSyntax
Dim token = syntaxTree.GetRoot(cancellationToken).FindToken(position)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册