static async Task UpdateDocument(ConcurrentDictionary <DocumentId, Dictionary <DeclaredSymbolInfoKind, List <DeclaredSymbolInfoWrapper> > > result, Microsoft.CodeAnalysis.Document document, CancellationToken cancellationToken) { var syntaxFactsService = document.GetLanguageService <ISyntaxFactsService> (); var declaredSymbolInfoService = document.GetLanguageService <IDeclaredSymbolInfoFactoryService> (); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var infos = new Dictionary <DeclaredSymbolInfoKind, List <DeclaredSymbolInfoWrapper> > (); var stringTable = Roslyn.Utilities.StringTable.GetInstance(); // TODO: fix this foreach (var kind in AllKinds) { infos [kind] = new List <DeclaredSymbolInfoWrapper> (); } foreach (var current in root.DescendantNodesAndSelf(n => !(n is BlockSyntax))) { cancellationToken.ThrowIfCancellationRequested(); var kind = current.Kind(); if (kind == SyntaxKind.ConstructorDeclaration || kind == SyntaxKind.IndexerDeclaration) { continue; } if (declaredSymbolInfoService.TryGetDeclaredSymbolInfo(stringTable, current, out DeclaredSymbolInfo info)) { var declaredSymbolInfo = new DeclaredSymbolInfoWrapper(current, document.Id, info); infos[info.Kind].Add(declaredSymbolInfo); } } RemoveDocument(result, document.Id); result.TryAdd(document.Id, infos); }
protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); InvocationExpressionSyntax invocationExpression; if (!TryGetInvocationExpression(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out invocationExpression)) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(invocationExpression, cancellationToken).ConfigureAwait(false); var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); if (within == null) { return null; } var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>(); var methodGroup = semanticModel.GetMemberGroup(invocationExpression.Expression, cancellationToken) .OfType<IMethodSymbol>() .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation) .Sort(symbolDisplayService, semanticModel, invocationExpression.SpanStart); var expressionType = semanticModel.GetTypeInfo(invocationExpression.Expression, cancellationToken).Type as INamedTypeSymbol; var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>(); var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>(); var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(invocationExpression.ArgumentList); var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); if (methodGroup.Any()) { return CreateSignatureHelpItems( GetMethodGroupItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, methodGroup, cancellationToken), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); } else if (expressionType != null && expressionType.TypeKind == TypeKind.Delegate) { return CreateSignatureHelpItems( GetDelegateInvokeItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, expressionType, cancellationToken), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); } else { return null; } }
protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (!TryGetInvocationExpression(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out var invocationExpression)) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(invocationExpression, cancellationToken).ConfigureAwait(false); var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); if (within == null) { return null; } // get the regular signature help items var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>(); var methodGroup = semanticModel.GetMemberGroup(invocationExpression.Expression, cancellationToken) .OfType<IMethodSymbol>() .ToImmutableArray() .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation); // try to bind to the actual method var symbolInfo = semanticModel.GetSymbolInfo(invocationExpression, cancellationToken); var matchedMethodSymbol = symbolInfo.Symbol as IMethodSymbol; // if the symbol could be bound, replace that item in the symbol list if (matchedMethodSymbol != null && matchedMethodSymbol.IsGenericMethod) { methodGroup = methodGroup.SelectAsArray(m => matchedMethodSymbol.OriginalDefinition == m ? matchedMethodSymbol : m); } methodGroup = methodGroup.Sort( symbolDisplayService, semanticModel, invocationExpression.SpanStart); var expressionType = semanticModel.GetTypeInfo(invocationExpression.Expression, cancellationToken).Type as INamedTypeSymbol; var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>(); var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>(); var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(invocationExpression.ArgumentList); var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); if (methodGroup.Any()) { return CreateSignatureHelpItems( GetMethodGroupItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, methodGroup, cancellationToken), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); } else if (expressionType != null && expressionType.TypeKind == TypeKind.Delegate) { return CreateSignatureHelpItems( GetDelegateInvokeItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, expressionType, cancellationToken), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); } else { return null; } }
public async Task<Document> AddSourceToAsync(Document document, ISymbol symbol, CancellationToken cancellationToken) { if (document == null) { throw new ArgumentNullException(nameof(document)); } var newSemanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var rootNamespace = newSemanticModel.GetEnclosingNamespace(0, cancellationToken); // Add the interface of the symbol to the top of the root namespace document = await CodeGenerator.AddNamespaceOrTypeDeclarationAsync( document.Project.Solution, rootNamespace, CreateCodeGenerationSymbol(document, symbol), CreateCodeGenerationOptions(newSemanticModel.SyntaxTree.GetLocation(new TextSpan()), symbol), cancellationToken).ConfigureAwait(false); var docCommentFormattingService = document.GetLanguageService<IDocumentationCommentFormattingService>(); var docWithDocComments = await ConvertDocCommentsToRegularComments(document, docCommentFormattingService, cancellationToken).ConfigureAwait(false); var docWithAssemblyInfo = await AddAssemblyInfoRegionAsync(docWithDocComments, symbol.GetOriginalUnreducedDefinition(), cancellationToken).ConfigureAwait(false); var node = await docWithAssemblyInfo.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var formattedDoc = await Formatter.FormatAsync( docWithAssemblyInfo, SpecializedCollections.SingletonEnumerable(node.FullSpan), options: null, rules: GetFormattingRules(docWithAssemblyInfo), cancellationToken: cancellationToken).ConfigureAwait(false); var reducers = this.GetReducers(); return await Simplifier.ReduceAsync(formattedDoc, reducers, null, cancellationToken).ConfigureAwait(false); }
private static INamespaceOrTypeSymbol CreateCodeGenerationSymbol(Document document, ISymbol symbol) { symbol = symbol.GetOriginalUnreducedDefinition(); var topLevelNamespaceSymbol = symbol.ContainingNamespace; var topLevelNamedType = MetadataAsSourceHelpers.GetTopLevelContainingNamedType(symbol); var canImplementImplicitly = document.GetLanguageService<ISemanticFactsService>().SupportsImplicitInterfaceImplementation; var docCommentFormattingService = document.GetLanguageService<IDocumentationCommentFormattingService>(); INamespaceOrTypeSymbol wrappedType = new WrappedNamedTypeSymbol(topLevelNamedType, canImplementImplicitly, docCommentFormattingService); return topLevelNamespaceSymbol.IsGlobalNamespace ? wrappedType : CodeGenerationSymbolFactory.CreateNamespaceSymbol( topLevelNamespaceSymbol.ToDisplayString(SymbolDisplayFormats.NameFormat), null, new[] { wrappedType }); }
public override async Task<string> GetHelpTermAsync(Document document, TextSpan span, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); // For now, find the token under the start of the selection. var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = syntaxTree.GetTouchingToken(span.Start, cancellationToken, findInsideTrivia: true); if (IsValid(token, span)) { var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var result = TryGetText(token, semanticModel, document, cancellationToken, syntaxFacts); if (string.IsNullOrEmpty(result)) { var previousToken = token.GetPreviousToken(); if (IsValid(previousToken, span)) { result = TryGetText(previousToken, semanticModel, document, cancellationToken, syntaxFacts); } } return result; } var trivia = root.FindTrivia(span.Start, findInsideTrivia: true); if (trivia.Span.IntersectsWith(span) && trivia.Kind() == SyntaxKind.PreprocessingMessageTrivia && trivia.Token.GetAncestor<RegionDirectiveTriviaSyntax>() != null) { return "#region"; } if (trivia.IsRegularOrDocComment()) { // just find the first "word" that intersects with our position var text = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); int start = span.Start; int end = span.Start; while (start > 0 && syntaxFacts.IsIdentifierPartCharacter(text[start - 1])) { start--; } while (end < text.Length - 1 && syntaxFacts.IsIdentifierPartCharacter(text[end])) { end++; } return text.GetSubText(TextSpan.FromBounds(start, end)).ToString(); } return string.Empty; }
protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); ConstructorInitializerSyntax constructorInitializer; if (!TryGetConstructorInitializer(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out constructorInitializer)) { return null; } var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var within = semanticModel.GetEnclosingNamedType(position, cancellationToken); if (within == null) { return null; } if (within.TypeKind != TypeKind.Struct && within.TypeKind != TypeKind.Class) { return null; } var type = constructorInitializer.Kind() == SyntaxKind.BaseConstructorInitializer ? within.BaseType : within; if (type == null) { return null; } var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>(); var accessibleConstructors = type.InstanceConstructors .Where(c => c.IsAccessibleWithin(within)) .Where(c => c.IsEditorBrowsable(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)) .Sort(symbolDisplayService, semanticModel, constructorInitializer.SpanStart); if (!accessibleConstructors.Any()) { return null; } var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>(); var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>(); var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(constructorInitializer.ArgumentList); var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); return CreateSignatureHelpItems(accessibleConstructors.Select(c => Convert(c, constructorInitializer.ArgumentList.OpenParenToken, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); }
private static IEnumerable<CompletionListProvider> GetCompletionListProviders(Document document) { var languageService = document.GetLanguageService<ICompletionService>(); IEnumerable<CompletionListProvider> providers = null; if (languageService != null) { providers = InnerCompletionService.GetDefaultCompletionListProviders(document); if (_additionalProviders != null) { providers = providers.Concat(_additionalProviders); } } return providers; }
protected override async Task<CompletionItem> GetBuilderAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken = default(CancellationToken)) { if (triggerInfo.TriggerReason == CompletionTriggerReason.TypeCharCommand) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); if (triggerInfo.IsDebugger) { // Aggressive Intellisense in the debugger: always show the builder return CreateEmptyBuilder(text, position); } var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = tree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (token.Kind() == SyntaxKind.None) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false); var typeInferrer = document.GetLanguageService<ITypeInferenceService>(); if (IsLambdaExpression(semanticModel, position, token, typeInferrer, cancellationToken)) { return CreateBuilder(text, position, CSharpFeaturesResources.LambdaExpression, CSharpFeaturesResources.AutoselectDisabledDueToPotentialLambdaDeclaration); } else if (IsAnonymousObjectCreation(token)) { return CreateBuilder(text, position, CSharpFeaturesResources.MemberName, CSharpFeaturesResources.AutoselectDisabledDueToPossibleExplicitlyNamesAnonTypeMemCreation); } else if (token.IsPreProcessorExpressionContext()) { return CreateEmptyBuilder(text, position); } else if (IsImplicitArrayCreation(semanticModel, token, position, typeInferrer, cancellationToken)) { return CreateBuilder(text, position, CSharpFeaturesResources.ImplicitArrayCreation, CSharpFeaturesResources.AutoselectDisabledDueToPotentialImplicitArray); } else if (token.IsKindOrHasMatchingText(SyntaxKind.FromKeyword) || token.IsKindOrHasMatchingText(SyntaxKind.JoinKeyword)) { return CreateBuilder(text, position, CSharpFeaturesResources.RangeVariable, CSharpFeaturesResources.AutoselectDisabledDueToPotentialRangeVariableDecl); } } return null; }
protected override async Task<CompletionItem> GetSuggestionModeItemAsync(Document document, int position, TextSpan itemSpan, CompletionTrigger trigger, CancellationToken cancellationToken = default(CancellationToken)) { if (trigger.Kind == CompletionTriggerKind.Insertion) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = tree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (token.Kind() == SyntaxKind.None) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false); var typeInferrer = document.GetLanguageService<ITypeInferenceService>(); if (IsLambdaExpression(semanticModel, position, token, typeInferrer, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.LambdaExpression, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPotentialLambdaDeclaration); } else if (IsAnonymousObjectCreation(token) || IsPossibleTupleExpression(token)) { return CreateSuggestionModeItem(CSharpFeaturesResources.MemberName, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPossibleExplicitlyNamesAnonTypeMemCreation); } else if (token.IsPreProcessorExpressionContext()) { return CreateEmptySuggestionModeItem(itemSpan); } else if (IsImplicitArrayCreation(semanticModel, token, position, typeInferrer, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.ImplicitArrayCreation, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPotentialImplicitArray); } else if (token.IsKindOrHasMatchingText(SyntaxKind.FromKeyword) || token.IsKindOrHasMatchingText(SyntaxKind.JoinKeyword)) { return CreateSuggestionModeItem(CSharpFeaturesResources.RangeVariable, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPotentialRangeVariableDecl); } else if (tree.IsNamespaceDeclarationNameContext(position, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.NamespaceName, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToNamespaceDeclaration); } } return null; }
internal override Task<Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, string diagnosticId, CancellationToken cancellationToken) { //// We are going to add a call Dispose on fields: //// //// public void Dispose() //// { //// A.Dispose(); //// ... //// } var syntaxNode = nodeToFix as VariableDeclaratorSyntax; if (syntaxNode == null) { return Task.FromResult(document); } // find a Dispose method var member = syntaxNode.FirstAncestorOrSelf<ClassDeclarationSyntax>() .DescendantNodes().OfType<MethodDeclarationSyntax>() .Where(n => n.Identifier.ValueText == CA2213DiagnosticAnalyzer.Dispose).FirstOrDefault(); if (member == null) { return Task.FromResult(document); } var factory = document.GetLanguageService<SyntaxGenerator>(); var symbol = model.GetDeclaredSymbol(syntaxNode); // handle a case where a local in the Dipose method with the same name by generating this (or ClassName) and simplifying it var path = symbol.IsStatic ? factory.IdentifierName(symbol.ContainingType.MetadataName) : factory.ThisExpression(); var statement = factory.ExpressionStatement( factory.InvocationExpression( factory.MemberAccessExpression( factory.MemberAccessExpression(path, factory.IdentifierName(symbol.Name)).WithAdditionalAnnotations(Simplification.Simplifier.Annotation), factory.IdentifierName(CA2213DiagnosticAnalyzer.Dispose)))); var newMember = member.AddBodyStatements((StatementSyntax)statement).WithAdditionalAnnotations(Formatter.Annotation); return Task.FromResult(document.WithSyntaxRoot(root.ReplaceNode(member, newMember))); }
protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); AttributeSyntax attribute; if (!TryGetAttributeExpression(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out attribute)) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(attribute, cancellationToken).ConfigureAwait(false); var attributeType = semanticModel.GetTypeInfo(attribute, cancellationToken).Type as INamedTypeSymbol; if (attributeType == null) { return null; } var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); if (within == null) { return null; } var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>(); var accessibleConstructors = attributeType.InstanceConstructors .WhereAsArray(c => c.IsAccessibleWithin(within)) .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation) .Sort(symbolDisplayService, semanticModel, attribute.SpanStart); if (!accessibleConstructors.Any()) { return null; } var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>(); var documentationCommentFormatter = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>(); var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(attribute.ArgumentList); var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); return CreateSignatureHelpItems(accessibleConstructors.Select(c => Convert(c, within, attribute, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormatter, cancellationToken)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); }
public IndentationResult? GetDesiredIndentation(Document document, int lineNumber, CancellationToken cancellationToken) { var root = document.GetSyntaxRootSynchronously(cancellationToken); var sourceText = root.SyntaxTree.GetText(cancellationToken); var documentOptions = document.GetOptionsAsync(cancellationToken).WaitAndGetResult(cancellationToken); var lineToBeIndented = sourceText.Lines[lineNumber]; var formattingRules = GetFormattingRules(document, lineToBeIndented.Start); // enter on a token case. if (ShouldUseSmartTokenFormatterInsteadOfIndenter(formattingRules, root, lineToBeIndented, documentOptions, cancellationToken)) { return null; } var indenter = GetIndenter( document.GetLanguageService<ISyntaxFactsService>(), root.SyntaxTree, lineToBeIndented, formattingRules, documentOptions, cancellationToken); return indenter.GetDesiredIndentation(); }
protected override async Task<CodeIssue> GetIssueAsync( Document document, SyntaxNode node, CancellationToken cancellationToken) { if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) { return null; } var service = document.GetLanguageService<IImplementAbstractClassService>(); var result = await service.ImplementAbstractClassAsync(document, node, cancellationToken).ConfigureAwait(false); var changes = await result.GetTextChangesAsync(document, cancellationToken).ConfigureAwait(false); if (!changes.Any()) { return null; } return new CodeIssue( CodeIssueKind.Error, node.Span, SpecializedCollections.SingletonEnumerable(new CodeAction(result))); }
protected override async Task<CompletionItem> GetSuggestionModeItemAsync( Document document, int position, TextSpan itemSpan, CompletionTrigger trigger, CancellationToken cancellationToken = default(CancellationToken)) { if (trigger.Kind == CompletionTriggerKind.Insertion) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = tree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (token.Kind() == SyntaxKind.None) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false); var typeInferrer = document.GetLanguageService<ITypeInferenceService>(); if (IsLambdaExpression(semanticModel, position, token, typeInferrer, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.lambda_expression, CSharpFeaturesResources.Autoselect_disabled_due_to_potential_lambda_declaration); } else if (IsAnonymousObjectCreation(token)) { return CreateSuggestionModeItem(CSharpFeaturesResources.member_name, CSharpFeaturesResources.Autoselect_disabled_due_to_possible_explicitly_named_anonymous_type_member_creation); } else if (token.IsPreProcessorExpressionContext()) { return CreateEmptySuggestionModeItem(); } else if (IsImplicitArrayCreation(semanticModel, token, position, typeInferrer, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.implicit_array_creation, CSharpFeaturesResources.Autoselect_disabled_due_to_potential_implicit_array_creation); } else if (token.IsKindOrHasMatchingText(SyntaxKind.FromKeyword) || token.IsKindOrHasMatchingText(SyntaxKind.JoinKeyword)) { return CreateSuggestionModeItem(CSharpFeaturesResources.range_variable, CSharpFeaturesResources.Autoselect_disabled_due_to_potential_range_variable_declaration); } else if (tree.IsNamespaceDeclarationNameContext(position, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.namespace_name, CSharpFeaturesResources.Autoselect_disabled_due_to_namespace_declaration); } else if (tree.IsPartialTypeDeclarationNameContext(position, cancellationToken, out var typeDeclaration)) { switch (typeDeclaration.Keyword.Kind()) { case SyntaxKind.ClassKeyword: return CreateSuggestionModeItem(CSharpFeaturesResources.class_name, CSharpFeaturesResources.Autoselect_disabled_due_to_type_declaration); case SyntaxKind.StructKeyword: return CreateSuggestionModeItem(CSharpFeaturesResources.struct_name, CSharpFeaturesResources.Autoselect_disabled_due_to_type_declaration); case SyntaxKind.InterfaceKeyword: return CreateSuggestionModeItem(CSharpFeaturesResources.interface_name, CSharpFeaturesResources.Autoselect_disabled_due_to_type_declaration); } } else if (tree.IsPossibleDeconstructionDesignation(position, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.designation_name, CSharpFeaturesResources.Autoselect_disabled_due_to_possible_deconstruction_declaration); } } return null; }
protected IPropertySymbol GenerateProperty(string propertyName, string fieldName, Accessibility accessibility, IFieldSymbol field, INamedTypeSymbol containingSymbol, SyntaxAnnotation annotation, Document document, CancellationToken cancellationToken) { var factory = document.GetLanguageService<SyntaxGenerator>(); var propertySymbol = annotation.AddAnnotationToSymbol(CodeGenerationSymbolFactory.CreatePropertySymbol(containingType: containingSymbol, attributes: SpecializedCollections.EmptyList<AttributeData>(), accessibility: ComputeAccessibility(accessibility, field.Type), modifiers: new DeclarationModifiers().WithIsStatic (field.IsStatic).WithIsReadOnly (field.IsReadOnly).WithIsUnsafe (field.IsUnsafe()), type: field.Type, explicitInterfaceSymbol: null, name: propertyName, parameters: SpecializedCollections.EmptyList<IParameterSymbol>(), getMethod: CreateGet(fieldName, field, factory), setMethod: field.IsReadOnly || field.IsConst ? null : CreateSet(fieldName, field, factory))); return Simplifier.Annotation.AddAnnotationToSymbol( Formatter.Annotation.AddAnnotationToSymbol(propertySymbol)); }
protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken) { var root = await document.GetCSharpSyntaxRootAsync(cancellationToken).ConfigureAwait(false); ExpressionSyntax expression; SyntaxToken openBrace; if (!TryGetElementAccessExpression(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out expression, out openBrace)) { return null; } var semanticModel = await document.GetCSharpSemanticModelAsync(cancellationToken).ConfigureAwait(false); var expressionSymbol = semanticModel.GetSymbolInfo(expression, cancellationToken).GetAnySymbol(); if (expressionSymbol is INamedTypeSymbol) { // foo?[$$] var namedType = (INamedTypeSymbol)expressionSymbol; if (namedType.ConstructedFrom.SpecialType == SpecialType.System_Nullable_T && expression.IsKind(SyntaxKind.NullableType) && expression.IsChildNode<ArrayTypeSyntax>(a => a.ElementType)) { // Speculatively bind the type part of the nullable as an expression var nullableTypeSyntax = (NullableTypeSyntax)expression; var speculativeBinding = semanticModel.GetSpeculativeSymbolInfo(position, nullableTypeSyntax.ElementType, SpeculativeBindingOption.BindAsExpression); expressionSymbol = speculativeBinding.GetAnySymbol(); expression = nullableTypeSyntax.ElementType; } } if (expressionSymbol != null && expressionSymbol is INamedTypeSymbol) { return null; } IEnumerable<IPropertySymbol> indexers; ITypeSymbol expressionType; if (!TryGetIndexers(position, semanticModel, expression, cancellationToken, out indexers, out expressionType) && !TryGetComIndexers(semanticModel, expression, cancellationToken, out indexers, out expressionType)) { return null; } var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); if (within == null) { return null; } var accessibleIndexers = indexers.Where(m => m.IsAccessibleWithin(within, throughTypeOpt: expressionType)); if (!accessibleIndexers.Any()) { return null; } var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>(); accessibleIndexers = accessibleIndexers.FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation) .Sort(symbolDisplayService, semanticModel, expression.SpanStart); var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>(); var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>(); var textSpan = GetTextSpan(expression, openBrace); var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); return CreateSignatureHelpItems(accessibleIndexers.Select(p => Convert(p, openBrace, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); }
protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxToken genericIdentifier, lessThanToken; if (!TryGetGenericIdentifier(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out genericIdentifier, out lessThanToken)) { return null; } var simpleName = genericIdentifier.Parent as SimpleNameSyntax; if (simpleName == null) { return null; } var beforeDotExpression = simpleName.IsRightSideOfDot() ? simpleName.GetLeftSideOfDot() : null; var semanticModel = await document.GetSemanticModelForNodeAsync(simpleName, cancellationToken).ConfigureAwait(false); var leftSymbol = beforeDotExpression == null ? null : semanticModel.GetSymbolInfo(beforeDotExpression, cancellationToken).GetAnySymbol() as INamespaceOrTypeSymbol; var leftType = beforeDotExpression == null ? null : semanticModel.GetTypeInfo(beforeDotExpression, cancellationToken).Type as INamespaceOrTypeSymbol; var leftContainer = leftSymbol ?? leftType; var isBaseAccess = beforeDotExpression is BaseExpressionSyntax; var namespacesOrTypesOnly = SyntaxFacts.IsInNamespaceOrTypeContext(simpleName); var includeExtensions = leftSymbol == null && leftType != null; var name = genericIdentifier.ValueText; var symbols = isBaseAccess ? semanticModel.LookupBaseMembers(position, name) : namespacesOrTypesOnly ? semanticModel.LookupNamespacesAndTypes(position, leftContainer, name) : semanticModel.LookupSymbols(position, leftContainer, name, includeExtensions); var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); if (within == null) { return null; } var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>(); var accessibleSymbols = symbols.Where(s => s.GetArity() > 0) .Where(s => s is INamedTypeSymbol || s is IMethodSymbol) .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation) .Sort(symbolDisplayService, semanticModel, genericIdentifier.SpanStart); if (!accessibleSymbols.Any()) { return null; } var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>(); var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>(); var textSpan = GetTextSpan(genericIdentifier, lessThanToken); var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); return CreateSignatureHelpItems(accessibleSymbols.Select(s => Convert(s, lessThanToken, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); }
protected static async Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentUsingIdentifierAsync( string identifier, Document document, Func<SyntaxToken, SemanticModel, ValueTuple<bool, CandidateReason>> symbolsMatch, CancellationToken cancellationToken) { var tokens = await document.GetIdentifierOrGlobalNamespaceTokensWithTextAsync(identifier, cancellationToken).ConfigureAwait(false); var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); Func<SyntaxToken, bool> tokensMatch = t => IdentifiersMatch(syntaxFacts, identifier, t); return await FindReferencesInTokensAsync( document, tokens, tokensMatch, symbolsMatch, cancellationToken).ConfigureAwait(false); }
internal override Document AddImports( Document document, int position, XElement snippetNode, bool placeSystemNamespaceFirst, CancellationToken cancellationToken) { var importsNode = snippetNode.Element(XName.Get("Imports", snippetNode.Name.NamespaceName)); if (importsNode == null || !importsNode.HasElements) { return document; } var root = document.GetSyntaxRootSynchronously(cancellationToken); var contextLocation = root.FindToken(position).Parent; var newUsingDirectives = GetUsingDirectivesToAdd(contextLocation, snippetNode, importsNode, cancellationToken); if (!newUsingDirectives.Any()) { return document; } // In Venus/Razor, inserting imports statements into the subject buffer does not work. // Instead, we add the imports through the contained language host. if (TryAddImportsToContainedDocument(document, newUsingDirectives.Where(u => u.Alias == null).Select(u => u.Name.ToString()))) { return document; } var addImportService = document.GetLanguageService<IAddImportsService>(); var compilation = document.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken); var newRoot = addImportService.AddImports(compilation, root, contextLocation, newUsingDirectives, placeSystemNamespaceFirst); var newDocument = document.WithSyntaxRoot(newRoot); var formattedDocument = Formatter.FormatAsync(newDocument, Formatter.Annotation, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken); document.Project.Solution.Workspace.ApplyDocumentChanges(formattedDocument, cancellationToken); return formattedDocument; }
private static async Task<ImmutableArray<ReferenceLocation>> FindReferencesThroughAliasSymbolsAsync( ISymbol symbol, Document document, ImmutableArray<IAliasSymbol> aliasSymbols, Func<SyntaxToken, SemanticModel, ValueTuple<bool, CandidateReason>> symbolsMatch, CancellationToken cancellationToken) { var syntaxFactsService = document.GetLanguageService<ISyntaxFactsService>(); var allAliasReferences = ArrayBuilder<ReferenceLocation>.GetInstance(); foreach (var aliasSymbol in aliasSymbols) { var aliasReferences = await FindReferencesInDocumentUsingIdentifierAsync(aliasSymbol.Name, document, symbolsMatch, cancellationToken).ConfigureAwait(false); allAliasReferences.AddRange(aliasReferences); // the alias may reference an attribute and the alias name may end with an "Attribute" suffix. In this case search for the // shortened name as well (e.g. using FooAttribute = MyNamespace.FooAttribute; [Foo] class C1 {}) string simpleName; if (TryGetNameWithoutAttributeSuffix(aliasSymbol.Name, syntaxFactsService, out simpleName)) { aliasReferences = await FindReferencesInDocumentUsingIdentifierAsync(simpleName, document, symbolsMatch, cancellationToken).ConfigureAwait(false); allAliasReferences.AddRange(aliasReferences); } } return allAliasReferences.ToImmutableAndFree(); }
private static Dictionary<string, List<int>> CreateIdentifierLocations(Document document, SyntaxNode root, CancellationToken cancellationToken) { var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); var identifierMap = SharedPools.StringIgnoreCaseDictionary<List<int>>().AllocateAndClear(); foreach (var token in root.DescendantTokens(descendIntoTrivia: true)) { if (token.IsMissing || token.Span.Length == 0) { continue; } if (syntaxFacts.IsIdentifier(token) || syntaxFacts.IsGlobalNamespaceKeyword(token)) { var valueText = token.ValueText; identifierMap.GetOrAdd(valueText, _ => SharedPools.BigDefault<List<int>>().AllocateAndClear()).Add(token.Span.Start); } } return identifierMap; }
private async Task<ClassifiedSpansAndHighlightSpan> GetTaggedTextForReferenceAsync( Document document, TextSpan referenceSpan, TextSpan widenedSpan) { var classificationService = document.GetLanguageService<IEditorClassificationService>(); if (classificationService == null) { return new ClassifiedSpansAndHighlightSpan(ImmutableArray<ClassifiedSpan>.Empty, new TextSpan()); } // Call out to the individual language to classify the chunk of text around the // reference. We'll get both the syntactic and semantic spans for this region. // Because the semantic tags may override the semantic ones (for example, // "DateTime" might be syntactically an identifier, but semantically a struct // name), we'll do a later merging step to get the final correct list of // classifications. For tagging, normally the editor handles this. But as // we're producing the list of Inlines ourselves, we have to handles this here. var syntaxSpans = new List<ClassifiedSpan>(); var semanticSpans = new List<ClassifiedSpan>(); var sourceText = await document.GetTextAsync(CancellationToken).ConfigureAwait(false); await classificationService.AddSyntacticClassificationsAsync( document, widenedSpan, syntaxSpans, CancellationToken).ConfigureAwait(false); await classificationService.AddSemanticClassificationsAsync( document, widenedSpan, semanticSpans, CancellationToken).ConfigureAwait(false); var classifiedSpans = MergeClassifiedSpans( syntaxSpans, semanticSpans, widenedSpan, sourceText); var highlightSpan = new TextSpan( start: referenceSpan.Start - widenedSpan.Start, length: referenceSpan.Length); return new ClassifiedSpansAndHighlightSpan(classifiedSpans, highlightSpan); }
private bool TryGetTextForOperator(SyntaxToken token, Document document, out string text) { var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); if (syntaxFacts.IsOperator(token) || syntaxFacts.IsPredefinedOperator(token) || SyntaxFacts.IsAssignmentExpressionOperatorToken(token.Kind())) { text = Keyword(syntaxFacts.GetText(token.RawKind)); return true; } if (token.IsKind(SyntaxKind.ColonColonToken)) { text = "::_CSharpKeyword"; return true; } if (token.Kind() == SyntaxKind.ColonToken && token.Parent is NameColonSyntax) { text = "cs_namedParameter"; return true; } if (token.IsKind(SyntaxKind.QuestionToken) && token.Parent is ConditionalExpressionSyntax) { text = "?_CSharpKeyword"; return true; } if (token.IsKind(SyntaxKind.EqualsGreaterThanToken)) { text = "=>_CSharpKeyword"; return true; } if (token.IsKind(SyntaxKind.PlusEqualsToken)) { text = "+=_CSharpKeyword"; return true; } if (token.IsKind(SyntaxKind.MinusEqualsToken)) { text = "-=_CSharpKeyword"; return true; } text = null; return false; }
private bool TryGetTextForSymbol(SyntaxToken token, SemanticModel semanticModel, Document document, CancellationToken cancellationToken, out string text) { ISymbol symbol; if (token.Parent is TypeArgumentListSyntax) { var genericName = token.GetAncestor<GenericNameSyntax>(); symbol = semanticModel.GetSymbolInfo(genericName, cancellationToken).Symbol ?? semanticModel.GetTypeInfo(genericName, cancellationToken).Type; } else if (token.Parent is NullableTypeSyntax && token.IsKind(SyntaxKind.QuestionToken)) { text = "System.Nullable`1"; return true; } else { var symbols = semanticModel.GetSymbols(token, document.Project.Solution.Workspace, bindLiteralsToUnderlyingType: true, cancellationToken: cancellationToken); symbol = symbols.FirstOrDefault(); if (symbol == null) { var bindableParent = document.GetLanguageService<ISyntaxFactsService>().GetBindableParent(token); var overloads = semanticModel.GetMemberGroup(bindableParent); symbol = overloads.FirstOrDefault(); } } // Local: return the name if it's the declaration, otherwise the type if (symbol is ILocalSymbol && !symbol.DeclaringSyntaxReferences.Any(d => d.GetSyntax().DescendantTokens().Contains(token))) { symbol = ((ILocalSymbol)symbol).Type; } // Range variable: use the type if (symbol is IRangeVariableSymbol) { var info = semanticModel.GetTypeInfo(token.Parent, cancellationToken); symbol = info.Type; } // Just use syntaxfacts for operators if (symbol is IMethodSymbol && ((IMethodSymbol)symbol).MethodKind == MethodKind.BuiltinOperator) { text = null; return false; } text = symbol != null ? Format(symbol) : null; return symbol != null; }
private async Task<ValueTuple<SemanticModel, IList<ISymbol>>> BindTokenAsync( Document document, SyntaxToken token, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false); var enclosingType = semanticModel.GetEnclosingNamedType(token.SpanStart, cancellationToken); var symbols = semanticModel.GetSymbols(token, document.Project.Solution.Workspace, bindLiteralsToUnderlyingType: true, cancellationToken: cancellationToken); var bindableParent = document.GetLanguageService<ISyntaxFactsService>().GetBindableParent(token); var overloads = semanticModel.GetMemberGroup(bindableParent, cancellationToken); symbols = symbols.Where(IsOk) .Where(s => IsAccessible(s, enclosingType)) .Concat(overloads) .Distinct(SymbolEquivalenceComparer.Instance); if (symbols.Any()) { var typeParameter = symbols.First() as ITypeParameterSymbol; return new ValueTuple<SemanticModel, IList<ISymbol>>( semanticModel, typeParameter != null && typeParameter.TypeParameterKind == TypeParameterKind.Cref ? SpecializedCollections.EmptyList<ISymbol>() : symbols.ToList()); } // Couldn't bind the token to specific symbols. If it's an operator, see if we can at // least bind it to a type. var syntaxFacts = document.Project.LanguageServices.GetService<ISyntaxFactsService>(); if (syntaxFacts.IsOperator(token)) { var typeInfo = semanticModel.GetTypeInfo(token.Parent, cancellationToken); if (IsOk(typeInfo.Type)) { return new ValueTuple<SemanticModel, IList<ISymbol>>(semanticModel, new List<ISymbol>(1) { typeInfo.Type }); } } return ValueTuple.Create(semanticModel, SpecializedCollections.EmptyList<ISymbol>()); }
/// <summary> /// Ensure that an event handler exists for a given event. /// </summary> /// <param name="thisDocument">The document corresponding to this operation.</param> /// <param name="targetDocument">The document to generate the event handler in if it doesn't /// exist.</param> /// <param name="className">The name of the type to generate the event handler in.</param> /// <param name="objectName">The name of the event member (if <paramref /// name="useHandlesClause"/> is true)</param> /// <param name="objectTypeName">The name of the type containing the event.</param> /// <param name="nameOfEvent">The name of the event member in <paramref /// name="objectTypeName"/></param> /// <param name="eventHandlerName">The name of the method to be hooked up to the /// event.</param> /// <param name="itemidInsertionPoint">The VS itemid of the file to generate the event /// handler in.</param> /// <param name="useHandlesClause">If true, a vb "Handles" clause will be generated for the /// handler.</param> /// <param name="additionalFormattingRule">An additional formatting rule that can be used to /// format the newly inserted method</param> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>Either the unique id of the method if it already exists, or the unique id of /// the to be generated method, the text of the to be generated method, and the position in /// <paramref name="itemidInsertionPoint"/> where the text should be inserted.</returns> public static Tuple<string, string, VsTextSpan> EnsureEventHandler( Document thisDocument, Document targetDocument, string className, string objectName, string objectTypeName, string nameOfEvent, string eventHandlerName, uint itemidInsertionPoint, bool useHandlesClause, IFormattingRule additionalFormattingRule, CancellationToken cancellationToken) { var thisCompilation = thisDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken); var type = thisCompilation.GetTypeByMetadataName(className); var existingEventHandlers = GetCompatibleEventHandlers(targetDocument, className, objectTypeName, nameOfEvent, cancellationToken); var existingHandler = existingEventHandlers.SingleOrDefault(e => e.Item1 == eventHandlerName); if (existingHandler != null) { return Tuple.Create(existingHandler.Item2, (string)null, default(VsTextSpan)); } // Okay, it doesn't exist yet. Let's create it. var codeGenerationService = targetDocument.GetLanguageService<ICodeGenerationService>(); var syntaxFactory = targetDocument.GetLanguageService<SyntaxGenerator>(); var eventMember = GetEventSymbol(thisDocument, objectTypeName, nameOfEvent, type, cancellationToken); if (eventMember == null) { throw new InvalidOperationException(); } var eventType = ((IEventSymbol)eventMember).Type; if (eventType.Kind != SymbolKind.NamedType || ((INamedTypeSymbol)eventType).DelegateInvokeMethod == null) { throw new InvalidOperationException(ServicesVSResources.EventTypeIsInvalid); } var handlesExpressions = useHandlesClause ? new[] { syntaxFactory.MemberAccessExpression( objectName != null ? syntaxFactory.IdentifierName(objectName) : syntaxFactory.ThisExpression(), syntaxFactory.IdentifierName(nameOfEvent)) } : null; var invokeMethod = ((INamedTypeSymbol)eventType).DelegateInvokeMethod; var newMethod = CodeGenerationSymbolFactory.CreateMethodSymbol( attributes: null, accessibility: Accessibility.Protected, modifiers: new DeclarationModifiers(), returnType: targetDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken).GetSpecialType(SpecialType.System_Void), explicitInterfaceSymbol: null, name: eventHandlerName, typeParameters: null, parameters: invokeMethod.Parameters.ToArray(), statements: null, handlesExpressions: handlesExpressions); var annotation = new SyntaxAnnotation(); newMethod = annotation.AddAnnotationToSymbol(newMethod); var codeModel = targetDocument.Project.LanguageServices.GetService<ICodeModelNavigationPointService>(); var syntaxFacts = targetDocument.Project.LanguageServices.GetService<ISyntaxFactsService>(); var targetSyntaxTree = targetDocument.GetSyntaxTreeAsync(cancellationToken).WaitAndGetResult(cancellationToken); var position = type.Locations.First(loc => loc.SourceTree == targetSyntaxTree).SourceSpan.Start; var destinationType = syntaxFacts.GetContainingTypeDeclaration(targetSyntaxTree.GetRoot(cancellationToken), position); var insertionPoint = codeModel.GetEndPoint(destinationType, EnvDTE.vsCMPart.vsCMPartBody); if (insertionPoint == null) { throw new InvalidOperationException(ServicesVSResources.MemberInsertionFailed); } var newType = codeGenerationService.AddMethod(destinationType, newMethod, new CodeGenerationOptions(autoInsertionLocation: false), cancellationToken); var newRoot = targetSyntaxTree.GetRoot(cancellationToken).ReplaceNode(destinationType, newType); newRoot = Simplifier.ReduceAsync(targetDocument.WithSyntaxRoot(newRoot), Simplifier.Annotation, null, cancellationToken).WaitAndGetResult(cancellationToken).GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken); var formattingRules = additionalFormattingRule.Concat(Formatter.GetDefaultFormattingRules(targetDocument)); var workspace = targetDocument.Project.Solution.Workspace; newRoot = Formatter.Format(newRoot, Formatter.Annotation, workspace, workspace.Options, formattingRules, cancellationToken); var newMember = newRoot.GetAnnotatedNodesAndTokens(annotation).Single(); var newMemberText = newMember.ToFullString(); // In VB, the final newline is likely a statement terminator in the parent - just add // one on so that things don't get messed. if (!newMemberText.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { newMemberText += Environment.NewLine; } return Tuple.Create(ConstructMemberId(newMethod), newMemberText, insertionPoint.Value.ToVsTextSpan()); }