protected override SyntaxToken GetToken( CompletionItem completionItem, SyntaxTree tree, CancellationToken cancellationToken ) { var tokenSpanEnd = MemberInsertionCompletionItem.GetTokenSpanEnd(completionItem); return(tree.FindTokenOnLeftOfPosition(tokenSpanEnd, cancellationToken)); }
protected override ISymbol GenerateMember(ISymbol newOverriddenMember, INamedTypeSymbol newContainingType, Document newDocument, MemberInsertionCompletionItem 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 modifiers = completionItem.Modifiers.WithIsUnsafe(completionItem.Modifiers.IsUnsafe | newOverriddenMember.IsUnsafe()); if (newOverriddenMember.Kind == SymbolKind.Method) { return syntaxFactory.OverrideMethod((IMethodSymbol)newOverriddenMember, modifiers, newContainingType, newDocument, cancellationToken); } else if (newOverriddenMember.Kind == SymbolKind.Property) { return syntaxFactory.OverrideProperty((IPropertySymbol)newOverriddenMember, modifiers, newContainingType, newDocument, cancellationToken); } else { return syntaxFactory.OverrideEvent((IEventSymbol)newOverriddenMember, modifiers, newContainingType); } }
protected override SyntaxToken GetToken(MemberInsertionCompletionItem completionItem, SyntaxTree tree, CancellationToken cancellationToken) { var token = completionItem.Token; return tree.FindTokenOnLeftOfPosition(token.Span.End, cancellationToken); }
protected abstract ISymbol GenerateMember(ISymbol member, INamedTypeSymbol containingType, Document document, MemberInsertionCompletionItem item, CancellationToken cancellationToken);
protected abstract SyntaxToken GetToken(MemberInsertionCompletionItem completionItem, SyntaxTree tree, CancellationToken cancellationToken);
private Document GenerateMemberAndUsings( Document document, MemberInsertionCompletionItem completionItem, ITextSnapshotLine 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 resolution = completionItem.SymbolId.Resolve(semanticModel.Compilation, cancellationToken: cancellationToken); var overriddenMember = GetResolvedSymbol(resolution, line.Extent.Span.ToTextSpan()); // CodeGenerationOptions containing before and after var options = new CodeGenerationOptions(contextLocation: semanticModel.SyntaxTree.GetLocation(TextSpan.FromBounds(line.Start, line.Start))); var generatedMember = GenerateMember(overriddenMember, containingType, document, completionItem, cancellationToken); 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; }
private Document DetermineNewDocument(MemberInsertionCompletionItem completionItem, ITextSnapshot textSnapshot, CancellationToken cancellationToken) { // The span we're going to replace var line = textSnapshot.GetLineFromLineNumber(completionItem.Line); 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); Document memberContainingDocument = GenerateMemberAndUsings(document, completionItem, line, cancellationToken); 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); }