| File: Completion\CompletionProviders\ObjectInitializerCompletionProvider.vb | Web Access |
| Project: src\roslyn\src\Features\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.Features.vbproj (Microsoft.CodeAnalysis.VisualBasic.Features) |
' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. Imports System.Collections.Immutable Imports System.Composition Imports System.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Completion Imports Microsoft.CodeAnalysis.Completion.Providers Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers <ExportCompletionProvider(NameOf(ObjectInitializerCompletionProvider), LanguageNames.VisualBasic), [Shared]> <ExtensionOrder(After:=NameOf(PreprocessorCompletionProvider))> Friend NotInheritable Class ObjectInitializerCompletionProvider Inherits AbstractObjectInitializerCompletionProvider <ImportingConstructor> <Obsolete(MefConstruction.ImportingConstructorMessage, True)> Public Sub New() End Sub Friend Overrides ReadOnly Property Language As String = LanguageNames.VisualBasic Protected Overrides Function GetInitializedMembers(tree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As HashSet(Of String) Dim token = tree.FindTokenOnLeftOfPosition(position, cancellationToken) token = token.GetPreviousTokenIfTouchingWord(position) ' The dot wasn't part of the identifier, so move over one more to get the , or { If token.Kind = SyntaxKind.DotToken Then token = token.GetPreviousToken() End If If token.Kind <> SyntaxKind.CommaToken AndAlso token.Kind <> SyntaxKind.OpenBraceToken Then Return New HashSet(Of String) End If Dim initializer = TryCast(token.Parent, ObjectMemberInitializerSyntax) If initializer Is Nothing Then Return New HashSet(Of String)() End If Return New HashSet(Of String)(initializer.Initializers.OfType(Of NamedFieldInitializerSyntax)().Select(Function(i) i.Name.Identifier.ValueText)) End Function Protected Overrides Function GetInitializedType( document As Document, semanticModel As SemanticModel, position As Integer, cancellationToken As CancellationToken) As (Type As ITypeSymbol, location As Location, isObjectInitializer As Boolean)? Dim tree = semanticModel.SyntaxTree If tree.IsInNonUserCode(position, cancellationToken) Then Return Nothing End If Dim token = tree.FindTokenOnLeftOfPosition(position, cancellationToken) token = token.GetPreviousTokenIfTouchingWord(position) ' We should have gotten a ".", since that all we want to come up on If token.Kind <> SyntaxKind.DotToken Then Return Nothing End If ' The dot must be following a comma or open brace Dim commaOrBrace = token.GetPreviousToken() If commaOrBrace.Kind <> SyntaxKind.CommaToken AndAlso commaOrBrace.Kind <> SyntaxKind.OpenBraceToken Then Return Nothing End If ' We have the right tokens. Get the containing object initializer. Will we be able to walk ' up and determine the type? Dim containingInitializer = commaOrBrace.Parent If containingInitializer Is Nothing OrElse containingInitializer.Parent Is Nothing OrElse containingInitializer.Kind <> SyntaxKind.ObjectMemberInitializer Then Return Nothing End If ' Get the grandparent object creation expression Dim objectCreationExpression = TryCast(containingInitializer.Parent, ObjectCreationExpressionSyntax) If objectCreationExpression Is Nothing Then Return Nothing End If Dim initializerLocation As Location = token.GetLocation() Dim symbolInfo = semanticModel.GetSymbolInfo(objectCreationExpression.Type, cancellationToken) Dim symbol = TryCast(symbolInfo.Symbol, ITypeSymbol) Return (symbol, initializerLocation, isObjectInitializer:=True) End Function Public Overrides Function IsInsertionTrigger(text As SourceText, characterPosition As Integer, options As CompletionOptions) As Boolean Return text(characterPosition) = "."c End Function Public Overrides ReadOnly Property TriggerCharacters As ImmutableHashSet(Of Char) = ImmutableHashSet.Create("."c) Protected Overrides Function IsExclusiveAsync(document As Document, position As Integer, cancellationToken As CancellationToken) As Task(Of Boolean) ' Object initializers are explicitly indicated by "With", so we're always exclusive. Return SpecializedTasks.True End Function Protected Overrides Function IsInitializableFieldOrProperty(fieldOrProperty As ISymbol, containingType As INamedTypeSymbol) As Boolean ' Unlike CSharp, we don't want to suggest readonly members, even if they are Collections Return MyBase.IsInitializableFieldOrProperty(fieldOrProperty, containingType) AndAlso fieldOrProperty.IsWriteableFieldOrProperty() AndAlso IsValidProperty(fieldOrProperty) End Function Protected Overrides Function EscapeIdentifier(symbol As ISymbol) As String Return symbol.Name.EscapeIdentifier() End Function Private Shared Function IsValidProperty(member As ISymbol) As Boolean Dim [property] = TryCast(member, IPropertySymbol) If [property] IsNot Nothing Then Return [property].Parameters.IsDefaultOrEmpty OrElse [property].Parameters.All(Function(p) p.IsOptional OrElse p.IsParams) End If Return True End Function End Class End Namespace