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));
        }
        protected override ISymbol GenerateMember(ISymbol member, INamedTypeSymbol containingType, Document document, MemberInsertionCompletionItem item, CancellationToken cancellationToken)
        {
            var syntaxFactory = document.GetLanguageService<SyntaxGenerator>();
            var semanticModel = document.GetSemanticModelAsync(cancellationToken).WaitAndGetResult(cancellationToken);

            return CodeGenerationSymbolFactory.CreateMethodSymbol(attributes: new List<AttributeData>(),
                accessibility: Accessibility.NotApplicable,
                modifiers: item.Modifiers,
                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 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);
            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).WaitAndGetResult(cancellationToken);
            }
            else if (generatedMember.Kind == SymbolKind.Property)
            {
                memberContainingDocument = codeGenService.AddPropertyAsync(document.Project.Solution, containingType, (IPropertySymbol)generatedMember, options).WaitAndGetResult(cancellationToken);
            }
            else if (generatedMember.Kind == SymbolKind.Event)
            {
                memberContainingDocument = codeGenService.AddEventAsync(document.Project.Solution, containingType, (IEventSymbol)generatedMember, options).WaitAndGetResult(cancellationToken);
            }

            return(memberContainingDocument);
        }
 protected abstract ISymbol GenerateMember(ISymbol member, INamedTypeSymbol containingType, Document document, MemberInsertionCompletionItem item, CancellationToken cancellationToken);
 protected abstract SyntaxToken GetToken(MemberInsertionCompletionItem completionItem, SyntaxTree tree, CancellationToken cancellationToken);
 protected override SyntaxToken GetToken(MemberInsertionCompletionItem completionItem, SyntaxTree tree, CancellationToken cancellationToken)
 {
     var token = completionItem.Token;
     return tree.FindTokenOnLeftOfPosition(token.Span.End, cancellationToken);
 }
Beispiel #7
0
        protected override ISymbol GenerateMember(ISymbol member, INamedTypeSymbol containingType, Document document, MemberInsertionCompletionItem item, CancellationToken cancellationToken)
        {
            var syntaxFactory = document.GetLanguageService <SyntaxGenerator>();
            var semanticModel = document.GetSemanticModelAsync(cancellationToken).WaitAndGetResult(cancellationToken);

            return(CodeGenerationSymbolFactory.CreateMethodSymbol(attributes: new List <AttributeData>(),
                                                                  accessibility: Accessibility.NotApplicable,
                                                                  modifiers: item.Modifiers,
                                                                  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)));
        }