protected override Task <ISymbol> GenerateMemberAsync(ISymbol newOverriddenMember, INamedTypeSymbol newContainingType, Document newDocument, CompletionItem completionItem, CancellationToken cancellationToken) { // Special case: if you are overriding object.ToString(), we will make the return value as non-nullable. The return was made nullable because // are implementations out there that will return null, but that's not something we really want new implementations doing. We may need to consider // expanding this behavior to other methods in the future; if that is the case then we would want there to be an attribute on the return type // rather than updating this list, but for now there is no such attribute until we find more cases for it. See // https://github.com/dotnet/roslyn/issues/30317 for some additional conversation about this design decision. // // We don't check if methodSymbol.ContainingType is object, in case you're overriding something that is itself an override if (newOverriddenMember is IMethodSymbol methodSymbol && methodSymbol.Name == "ToString" && methodSymbol.Parameters.Length == 0) { newOverriddenMember = CodeGenerationSymbolFactory.CreateMethodSymbol(methodSymbol, returnType: methodSymbol.ReturnType.WithNullableAnnotation(NullableAnnotation.NotAnnotated)); } // Figure out what to insert, and do it. Throw if we've somehow managed to get this far and can't. var syntaxFactory = newDocument.GetLanguageService <SyntaxGenerator>(); var itemModifiers = MemberInsertionCompletionItem.GetModifiers(completionItem); var modifiers = itemModifiers.WithIsUnsafe(itemModifiers.IsUnsafe | newOverriddenMember.RequiresUnsafeModifier()); return(syntaxFactory.OverrideAsync( newOverriddenMember, newContainingType, newDocument, modifiers, cancellationToken)); }
private async Task <Document> DetermineNewDocumentAsync(CompletionItem completionItem, SourceText sourceText, CancellationToken cancellationToken) { // The span we're going to replace var line = sourceText.Lines[MemberInsertionCompletionItem.GetLine(completionItem)]; //var line = textSnapshot.GetLineFromLineNumber(MemberInsertionCompletionItem.GetLine(completionItem)); //var sourceText = textSnapshot.AsText(); var document = sourceText.GetOpenDocumentInCurrentContextWithChanges(); Contract.ThrowIfNull(document); // Annotate the line we care about so we can find it after adding usings var tree = document.GetSyntaxTreeAsync(cancellationToken).WaitAndGetResult(cancellationToken); var token = GetToken(completionItem, tree, cancellationToken); var annotatedRoot = tree.GetRoot(cancellationToken).ReplaceToken(token, token.WithAdditionalAnnotations(_otherAnnotation)); document = document.WithSyntaxRoot(annotatedRoot); var memberContainingDocument = await GenerateMemberAndUsingsAsync(document, completionItem, line, cancellationToken).ConfigureAwait(false); var insertionRoot = PrepareTreeForMemberInsertion(memberContainingDocument, cancellationToken); var insertionText = GenerateInsertionText(memberContainingDocument, cancellationToken); var destinationSpan = ComputeDestinationSpan(insertionRoot, insertionText); var finalText = insertionRoot.GetText(sourceText.Encoding).Replace(destinationSpan, insertionText.Trim()); document = document.WithText(finalText); var newRoot = document.GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken); var declaration = GetSyntax(newRoot.FindToken(destinationSpan.End)); document = document.WithSyntaxRoot(newRoot.ReplaceNode(declaration, declaration.WithAdditionalAnnotations(_annotation))); return(Formatter.FormatAsync(document, _annotation, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken)); }
protected override async Task <ISymbol> GenerateMemberAsync(ISymbol newOverriddenMember, INamedTypeSymbol newContainingType, Document newDocument, CompletionItem completionItem, CancellationToken cancellationToken) { // Figure out what to insert, and do it. Throw if we've somehow managed to get this far and can't. var syntaxFactory = newDocument.GetLanguageService <SyntaxGenerator>(); var codeGenService = newDocument.GetLanguageService <ICodeGenerationService>(); var itemModifiers = MemberInsertionCompletionItem.GetModifiers(completionItem); var modifiers = itemModifiers.WithIsUnsafe(itemModifiers.IsUnsafe | newOverriddenMember.IsUnsafe()); if (newOverriddenMember.Kind == SymbolKind.Method) { return(await syntaxFactory.OverrideMethodAsync((IMethodSymbol)newOverriddenMember, modifiers, newContainingType, newDocument, cancellationToken).ConfigureAwait(false)); } else if (newOverriddenMember.Kind == SymbolKind.Property) { return(await syntaxFactory.OverridePropertyAsync((IPropertySymbol)newOverriddenMember, modifiers, newContainingType, newDocument, cancellationToken).ConfigureAwait(false)); } else { return(syntaxFactory.OverrideEvent((IEventSymbol)newOverriddenMember, modifiers, newContainingType)); } }
protected override Task <ISymbol> GenerateMemberAsync(ISymbol newOverriddenMember, INamedTypeSymbol newContainingType, Document newDocument, CompletionItem completionItem, CancellationToken cancellationToken) { // Figure out what to insert, and do it. Throw if we've somehow managed to get this far and can't. var syntaxFactory = newDocument.GetLanguageService <SyntaxGenerator>(); var itemModifiers = MemberInsertionCompletionItem.GetModifiers(completionItem); var modifiers = itemModifiers.WithIsUnsafe(itemModifiers.IsUnsafe | newOverriddenMember.IsUnsafe()); return(syntaxFactory.OverrideAsync( newOverriddenMember, newContainingType, newDocument, modifiers, cancellationToken)); }
protected override async Task <ISymbol> GenerateMemberAsync(ISymbol member, INamedTypeSymbol containingType, Document document, CompletionItem item, CancellationToken cancellationToken) { var syntaxFactory = document.GetLanguageService <SyntaxGenerator>(); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var method = (IMethodSymbol)member; return(CodeGenerationSymbolFactory.CreateMethodSymbol( attributes: ImmutableArray <AttributeData> .Empty, accessibility: Accessibility.NotApplicable, modifiers: MemberInsertionCompletionItem.GetModifiers(item), returnType: semanticModel.Compilation.GetSpecialType(SpecialType.System_Void), returnsByRef: method.ReturnsByRef, explicitInterfaceImplementations: default,
private CompletionItem CreateItem(IMethodSymbol method, int line, TextSpan lineSpan, TextSpan span, SemanticModel semanticModel, DeclarationModifiers modifiers, Document document, SyntaxToken token) { modifiers = new DeclarationModifiers(method.IsStatic, isUnsafe: method.IsUnsafe(), isPartial: true, isAsync: modifiers.IsAsync); var displayText = GetDisplayText(method, semanticModel, span.Start); return(MemberInsertionCompletionItem.Create( displayText, modifiers, line, method, token, span.Start, rules: this.GetRules())); }
protected override async Task <ISymbol> GenerateMemberAsync(ISymbol member, INamedTypeSymbol containingType, Document document, CompletionItem item, CancellationToken cancellationToken) { var syntaxFactory = document.GetLanguageService <SyntaxGenerator>(); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); return(CodeGenerationSymbolFactory.CreateMethodSymbol(attributes: new List <AttributeData>(), accessibility: Accessibility.NotApplicable, modifiers: MemberInsertionCompletionItem.GetModifiers(item), returnType: semanticModel.Compilation.GetSpecialType(SpecialType.System_Void), explicitInterfaceSymbol: null, name: member.Name, typeParameters: ((IMethodSymbol)member).TypeParameters, parameters: member.GetParameters().Select(p => CodeGenerationSymbolFactory.CreateParameterSymbol(p.GetAttributes(), p.RefKind, p.IsParams, p.Type, p.Name)).ToList(), statements: syntaxFactory.CreateThrowNotImplementedStatementBlock(semanticModel.Compilation))); }
private CompletionItem CreateItem( ISymbol symbol, ISymbolDisplayService symbolDisplayService, SemanticModel semanticModel, SyntaxToken startToken, DeclarationModifiers modifiers) { var position = startToken.SpanStart; var displayString = symbolDisplayService.ToMinimalDisplayString(semanticModel, position, symbol, _overrideNameFormat); return(MemberInsertionCompletionItem.Create( displayString, modifiers, _startLineNumber, symbol, startToken, position, rules: _provider.GetRules())); }
private async Task <Document> DetermineNewDocumentAsync(Document document, CompletionItem completionItem, CancellationToken cancellationToken) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); // The span we're going to replace var line = text.Lines[MemberInsertionCompletionItem.GetLine(completionItem)]; // Annotate the line we care about so we can find it after adding usings var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = GetToken(completionItem, tree, cancellationToken); var annotatedRoot = tree.GetRoot(cancellationToken).ReplaceToken(token, token.WithAdditionalAnnotations(_otherAnnotation)); document = document.WithSyntaxRoot(annotatedRoot); var memberContainingDocument = await GenerateMemberAndUsingsAsync(document, completionItem, line, cancellationToken).ConfigureAwait(false); if (memberContainingDocument == null) { // Generating the new document failed because we somehow couldn't resolve // the underlying symbol's SymbolKey. At this point, we won't be able to // make any changes, so just return the document we started with. return(document); } var insertionRoot = await GetTreeWithAddedSyntaxNodeRemovedAsync(memberContainingDocument, cancellationToken).ConfigureAwait(false); var insertionText = await GenerateInsertionTextAsync(memberContainingDocument, cancellationToken).ConfigureAwait(false); var destinationSpan = ComputeDestinationSpan(insertionRoot); var finalText = insertionRoot.GetText(text.Encoding) .Replace(destinationSpan, insertionText.Trim()); document = document.WithText(finalText); var newRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var declaration = GetSyntax(newRoot.FindToken(destinationSpan.End)); document = document.WithSyntaxRoot(newRoot.ReplaceNode(declaration, declaration.WithAdditionalAnnotations(_annotation))); return(await Formatter.FormatAsync(document, _annotation, cancellationToken : cancellationToken).ConfigureAwait(false)); }
private async Task <Document> GenerateMemberAndUsingsAsync( Document document, CompletionItem completionItem, TextLine line, CancellationToken cancellationToken) { var syntaxFactory = document.GetLanguageService <SyntaxGenerator>(); var codeGenService = document.GetLanguageService <ICodeGenerationService>(); // Resolve member and type in our new, forked, solution var semanticModel = document.GetSemanticModelAsync(cancellationToken).WaitAndGetResult(cancellationToken); var containingType = semanticModel.GetEnclosingSymbol <INamedTypeSymbol>(line.Start, cancellationToken); var symbols = MemberInsertionCompletionItem.GetSymbolsAsync(completionItem, document, cancellationToken).WaitAndGetResult(cancellationToken); var overriddenMember = symbols.First(); // CodeGenerationOptions containing before and after var options = new CodeGenerationOptions(contextLocation: semanticModel.SyntaxTree.GetLocation(TextSpan.FromBounds(line.Start, line.Start))); var generatedMember = await GenerateMemberAsync(overriddenMember, containingType, document, completionItem, cancellationToken).ConfigureAwait(false); generatedMember = _annotation.AddAnnotationToSymbol(generatedMember); Document memberContainingDocument = null; if (generatedMember.Kind == SymbolKind.Method) { memberContainingDocument = codeGenService.AddMethodAsync(document.Project.Solution, containingType, (IMethodSymbol)generatedMember, options, cancellationToken).WaitAndGetResult(cancellationToken); } else if (generatedMember.Kind == SymbolKind.Property) { memberContainingDocument = codeGenService.AddPropertyAsync(document.Project.Solution, containingType, (IPropertySymbol)generatedMember, options, cancellationToken).WaitAndGetResult(cancellationToken); } else if (generatedMember.Kind == SymbolKind.Event) { memberContainingDocument = codeGenService.AddEventAsync(document.Project.Solution, containingType, (IEventSymbol)generatedMember, options, cancellationToken).WaitAndGetResult(cancellationToken); } return(memberContainingDocument); }
protected override Task<CompletionDescription> GetDescriptionWorkerAsync(Document document, CompletionItem item, CancellationToken cancellationToken) => MemberInsertionCompletionItem.GetDescriptionAsync(item, document, cancellationToken);
public override Task <CompletionDescription> GetDescriptionAsync(Document document, CompletionItem item, CancellationToken cancellationToken) { return(MemberInsertionCompletionItem.GetDescriptionAsync(item, document, cancellationToken)); }