Example #1
0
        public UCFG Create(SyntaxNode syntaxNode, IMethodSymbol methodSymbol, IControlFlowGraph cfg)
        {
            try
            {
                var ucfg = new UCFG
                {
                    Location = syntaxNode.GetUcfgLocation(),
                    MethodId = methodSymbol.ToUcfgMethodId()
                };

                ucfg.BasicBlocks.AddRange(cfg.Blocks.Select(this.blockBuilder.CreateBasicBlock));
                ucfg.Parameters.AddRange(methodSymbol.GetParameters().Select(p => p.Name));

                if (syntaxNode is BaseMethodDeclarationSyntax methodDeclaration &&
                    TaintAnalysisEntryPointDetector.IsEntryPoint(methodSymbol))
                {
                    var entryPointBlock = this.blockBuilder.CreateEntryPointBlock(methodDeclaration, methodSymbol, this.blockIdProvider.Get(cfg.EntryBlock));
                    ucfg.BasicBlocks.Add(entryPointBlock);
                    ucfg.Entries.Add(entryPointBlock.Id);
                }
                else
                {
                    ucfg.Entries.Add(this.blockIdProvider.Get(cfg.EntryBlock));
                }

                return(ucfg);
            }
Example #2
0
        private static bool SameParametersExceptFormatOrCulture(IMethodSymbol possibleOverload, IEnumerable <IParameterSymbol> invocationParameters)
        {
            var possibleOverloadParameters          = possibleOverload.GetParameters();
            var parametersWithoutFormatCulture      = possibleOverloadParameters.Where(p => !p.Type.IsAny(formatAndCultureType));
            var parametersWithoutFormatCultureCount = parametersWithoutFormatCulture.Count();

            // no FormatOrCulture argument found
            if (parametersWithoutFormatCultureCount == possibleOverloadParameters.Count())
            {
                return(false);
            }

            // once we filter out the FormatOrCulture argument, we have two possibilities:
            // - possibleOverload has a 'params' argument which matches the invocationParameters
            // - the number of parameters is the same and of same type

            var invocationParametersCount = invocationParameters.Count();

            if (parametersWithoutFormatCultureCount <= invocationParametersCount &&
                parametersWithoutFormatCultureCount > 0 &&
                parametersWithoutFormatCulture.Last().IsParams)
            {
                var overloadParametersList = parametersWithoutFormatCulture.ToList();
                var lastIndex = overloadParametersList.Count - 1;
                return(VerifyCompatibility(invocationParameters.ToList(), overloadParametersList, overloadParametersList[lastIndex]));
            }
            else if (invocationParametersCount == parametersWithoutFormatCultureCount)
            {
                return(VerifyCompatibility(invocationParameters.ToList(), parametersWithoutFormatCulture.ToList()));
            }
            return(false);
        }
        private static async Task <IMethodSymbol> OverrideMethodAsync(
            this SyntaxGenerator codeFactory,
            IMethodSymbol overriddenMethod,
            DeclarationModifiers modifiers,
            INamedTypeSymbol newContainingType,
            Document newDocument,
            CancellationToken cancellationToken)
        {
            // Abstract: Throw not implemented
            if (overriddenMethod.IsAbstract)
            {
                var compilation = await newDocument.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                var statement = codeFactory.CreateThrowNotImplementedStatement(compilation);

                return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                           overriddenMethod,
                           accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
                           modifiers: modifiers,
                           statements: ImmutableArray.Create(statement)));
            }
            else
            {
                // Otherwise, call the base method with the same parameters
                var typeParams = overriddenMethod.GetTypeArguments();
                var body       = codeFactory.InvocationExpression(
                    codeFactory.MemberAccessExpression(codeFactory.BaseExpression(),
                                                       typeParams.IsDefaultOrEmpty
                        ? codeFactory.IdentifierName(overriddenMethod.Name)
                        : codeFactory.GenericName(overriddenMethod.Name, typeParams)),
                    codeFactory.CreateArguments(overriddenMethod.GetParameters()));

                if (overriddenMethod.ReturnsByRef)
                {
                    body = codeFactory.RefExpression(body);
                }

                return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                           method: overriddenMethod,
                           accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
                           modifiers: modifiers,
                           statements: overriddenMethod.ReturnsVoid
                        ? ImmutableArray.Create(codeFactory.ExpressionStatement(body))
                        : ImmutableArray.Create(codeFactory.ReturnStatement(body))));
            }
        }
        public UCFG Build(SemanticModel semanticModel, SyntaxNode syntaxNode, IMethodSymbol methodSymbol, IControlFlowGraph cfg)
        {
            var ucfg = new UCFG
            {
                MethodId = GetMethodId(methodSymbol),
                Location = GetLocation(syntaxNode),
            };

            ucfg.BasicBlocks.AddRange(cfg.Blocks.Select(b => CreateBasicBlock(b, semanticModel)));
            ucfg.Parameters.AddRange(methodSymbol.GetParameters().Select(p => p.Name));

            if (syntaxNode is BaseMethodDeclarationSyntax methodDeclaration &&
                EntryPointRecognizer.IsEntryPoint(methodSymbol))
            {
                var entryPointBlock = CreateEntryPointBlock(semanticModel, methodDeclaration, methodSymbol, blockId.Get(cfg.EntryBlock));
                ucfg.BasicBlocks.Add(entryPointBlock);
                ucfg.Entries.Add(entryPointBlock.Id);
            }
Example #5
0
        private static bool SameParametersExceptWantedType(IMethodSymbol possibleOverload, IMethodSymbol invocationMethodSymbol, ImmutableArray <KnownType> types)
        {
            var withTypeParam = possibleOverload;

            if (possibleOverload.IsGenericMethod && invocationMethodSymbol.IsGenericMethod)
            {
                // attempt to create the possibleOverload method symbol with same type arguments as the invocation method
                withTypeParam = ConstructTypedPossibleOverload(possibleOverload, invocationMethodSymbol);
            }

            var invocationParameters             = invocationMethodSymbol.GetParameters();
            var parametersWithoutWantedType      = withTypeParam.GetParameters().Where(p => !p.Type.IsAny(types)).ToList();
            var parametersWithoutWantedTypeCount = parametersWithoutWantedType.Count;

            if (parametersWithoutWantedTypeCount == possibleOverload.GetParameters().Count())
            {
                return(false);
            }

            var invocationParametersCount = invocationParameters.Count();

            if (parametersWithoutWantedTypeCount <= invocationParametersCount &&
                parametersWithoutWantedTypeCount > 0 &&
                parametersWithoutWantedType.Last().IsParams)
            {
                // check whether has a parameter array argument which matches the invocationParameters
                var lastIndex = parametersWithoutWantedType.Count - 1;
                return(VerifyCompatibility(invocationParameters.ToList(), parametersWithoutWantedType, parametersWithoutWantedType[lastIndex]));
            }
            else if (invocationParametersCount == parametersWithoutWantedTypeCount)
            {
                // parameters must have the same type
                return(invocationParameters
                       .Select((p, index) => p.Type.DerivesOrImplements(parametersWithoutWantedType[index].Type))
                       .All(isCompatible => isCompatible));
            }
            return(false);
        }
Example #6
0
        private IEnumerable <CompletionItem> GetTagsForMethod(IMethodSymbol symbol, DocumentationCommentTriviaSyntax trivia)
        {
            var items = new List <CompletionItem>();

            var parameters     = symbol.GetParameters().Select(p => p.Name).ToSet();
            var typeParameters = symbol.TypeParameters.Select(t => t.Name).ToSet();

            RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, ParamTagName));
            RemoveExistingTags(trivia, typeParameters, x => AttributeSelector(x, TypeParamTagName));

            items.AddRange(parameters.Select(p => CreateCompletionItem(FormatParameter(ParamTagName, p))));
            items.AddRange(typeParameters.Select(t => CreateCompletionItem(FormatParameter(TypeParamTagName, t))));

            // Provide a return completion item in case the function returns something
            var returns = true;

            foreach (var node in trivia.Content)
            {
                var element = node as XmlElementSyntax;
                if (element != null && !element.StartTag.IsMissing && !element.EndTag.IsMissing)
                {
                    var startTag = element.StartTag;

                    if (startTag.Name.LocalName.ValueText == ReturnsTagName)
                    {
                        returns = false;
                        break;
                    }
                }
            }

            if (returns && !symbol.ReturnsVoid)
            {
                items.Add(CreateCompletionItem(ReturnsTagName));
            }

            return(items);
        }
Example #7
0
        public static IMethodSymbol OverrideMethod(
            this ISyntaxFactoryService codeFactory,
            IMethodSymbol overriddenMethod,
            SymbolModifiers modifiers,
            INamedTypeSymbol newContainingType,
            Document newDocument,
            CancellationToken cancellationToken)
        {
            // Abstract: Throw not implemented
            if (overriddenMethod.IsAbstract)
            {
                return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                           overriddenMethod,
                           accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
                           modifiers: modifiers,
                           statements: new[] { codeFactory.CreateThrowNotImplementStatement(newDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken)) }));
            }
            else
            {
                // Otherwise, call the base method with the same parameters
                var typeParams = overriddenMethod.GetTypeArguments();
                var body       = codeFactory.CreateInvocationExpression(
                    codeFactory.CreateMemberAccessExpression(codeFactory.CreateBaseExpression(),
                                                             typeParams.IsDefaultOrEmpty
                        ? codeFactory.CreateIdentifierName(overriddenMethod.Name)
                        : codeFactory.CreateGenericName(overriddenMethod.Name, typeParams)),
                    codeFactory.CreateArguments(overriddenMethod.GetParameters()));

                return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                           method: overriddenMethod,
                           accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
                           modifiers: modifiers,
                           statements: ((IMethodSymbol)overriddenMethod).ReturnsVoid
                        ? new SyntaxNode[] { codeFactory.CreateExpressionStatement(body) }
                        : new SyntaxNode[] { codeFactory.CreateReturnStatement(body) }));
            }
        }
 public static bool HasAnyStringComparisonParameter(IMethodSymbol method)
 {
     return(method.GetParameters()
            .Any(parameter => parameter.Type.Is(KnownType.System_StringComparison)));
 }
        public static async Task<IMethodSymbol> OverrideMethodAsync(
            this SyntaxGenerator codeFactory,
            IMethodSymbol overriddenMethod,
            DeclarationModifiers modifiers,
            INamedTypeSymbol newContainingType,
            Document newDocument,
            CancellationToken cancellationToken)
        {
            // Abstract: Throw not implemented
            if (overriddenMethod.IsAbstract)
            {
                var compilation = await newDocument.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
                return CodeGenerationSymbolFactory.CreateMethodSymbol(
                    overriddenMethod,
                    accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
                    modifiers: modifiers,
                    statements: new[] { codeFactory.CreateThrowNotImplementStatement(compilation) });
            }
            else
            {
                // Otherwise, call the base method with the same parameters
                var typeParams = overriddenMethod.GetTypeArguments();
                var body = codeFactory.InvocationExpression(
                    codeFactory.MemberAccessExpression(codeFactory.BaseExpression(),
                    typeParams.IsDefaultOrEmpty
                        ? codeFactory.IdentifierName(overriddenMethod.Name)
                        : codeFactory.GenericName(overriddenMethod.Name, typeParams)),
                    codeFactory.CreateArguments(overriddenMethod.GetParameters()));

                return CodeGenerationSymbolFactory.CreateMethodSymbol(
                    method: overriddenMethod,
                    accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
                    modifiers: modifiers,
                    statements: overriddenMethod.ReturnsVoid
                        ? new SyntaxNode[] { codeFactory.ExpressionStatement(body) }
                        : new SyntaxNode[] { codeFactory.ReturnStatement(body) });
            }
        }
Example #10
0
        private IEnumerable <CompletionData> GetTagsForMethod(CompletionEngine engine, IMethodSymbol symbol, TextSpan filterSpan, DocumentationCommentTriviaSyntax trivia, SyntaxToken token)
        {
            var items = new List <CompletionData>();

            var parameters     = symbol.GetParameters().Select(p => p.Name).ToSet();
            var typeParameters = symbol.TypeParameters.Select(t => t.Name).ToSet();

            // User is trying to write a name, try to suggest only names.
            if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) ||
                (token.Parent.IsKind(SyntaxKind.IdentifierName) && token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute)))
            {
                string parentElementName = null;

                var emptyElement = token.GetAncestor <XmlEmptyElementSyntax>();
                if (emptyElement != null)
                {
                    parentElementName = emptyElement.Name.LocalName.Text;
                }

                // We're writing the name of a paramref or typeparamref
                if (parentElementName == "paramref")
                {
                    items.AddRange(parameters.Select(p => engine.Factory.CreateXmlDocCompletionData(this, p)));
                }
                else if (parentElementName == "typeparamref")
                {
                    items.AddRange(typeParameters.Select(t => engine.Factory.CreateXmlDocCompletionData(this, t)));
                }

                return(items);
            }

            var returns = true;

            RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, "param"));
            RemoveExistingTags(trivia, typeParameters, x => AttributeSelector(x, "typeparam"));

            foreach (var node in trivia.Content)
            {
                var element = node as XmlElementSyntax;
                if (element != null && !element.StartTag.IsMissing && !element.EndTag.IsMissing)
                {
                    var startTag = element.StartTag;

                    if (startTag.Name.LocalName.ValueText == "returns")
                    {
                        returns = false;
                        break;
                    }
                }
            }

            items.AddRange(parameters.Select(p => engine.Factory.CreateXmlDocCompletionData(this, FormatParameter("param", p))));
            items.AddRange(typeParameters.Select(t => engine.Factory.CreateXmlDocCompletionData(this, FormatParameter("typeparam", t))));

            if (returns && !symbol.ReturnsVoid)
            {
                items.Add(engine.Factory.CreateXmlDocCompletionData(this, "returns"));
            }

            return(items);
        }
Example #11
0
 private static bool ReturnsOrAcceptsFormattableType(IMethodSymbol methodSymbol) =>
 methodSymbol.ReturnType.IsAny(formattableTypes) ||
 methodSymbol.GetParameters().Any(p => p.Type.IsAny(formattableTypes));
        private IEnumerable<CompletionItem> GetTagsForMethod(IMethodSymbol symbol, DocumentationCommentTriviaSyntax trivia)
        {
            var items = new List<CompletionItem>();

            var parameters = symbol.GetParameters().Select(p => p.Name).ToSet();
            var typeParameters = symbol.TypeParameters.Select(t => t.Name).ToSet();

            RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, ParamTagName));
            RemoveExistingTags(trivia, typeParameters, x => AttributeSelector(x, TypeParamTagName));

            items.AddRange(parameters.Select(p => CreateCompletionItem(FormatParameter(ParamTagName, p))));
            items.AddRange(typeParameters.Select(t => CreateCompletionItem(FormatParameter(TypeParamTagName, t))));

            // Provide a return completion item in case the function returns something
            var returns = true;

            foreach (var node in trivia.Content)
            {
                var element = node as XmlElementSyntax;
                if (element != null && !element.StartTag.IsMissing && !element.EndTag.IsMissing)
                {
                    var startTag = element.StartTag;

                    if (startTag.Name.LocalName.ValueText == ReturnsTagName)
                    {
                        returns = false;
                        break;
                    }
                }
            }

            if (returns && !symbol.ReturnsVoid)
            {
                items.Add(CreateCompletionItem(ReturnsTagName));
            }

            return items;
        }
        private IEnumerable<CompletionItem> GetTagsForMethod(IMethodSymbol symbol, TextSpan itemSpan, DocumentationCommentTriviaSyntax trivia, SyntaxToken token)
        {
            var items = new List<CompletionItem>();

            var parameters = symbol.GetParameters().Select(p => p.Name).ToSet();
            var typeParameters = symbol.TypeParameters.Select(t => t.Name).ToSet();

            // User is trying to write a name, try to suggest only names.
            if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) ||
                (token.Parent.IsKind(SyntaxKind.IdentifierName) && token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute)))
            {
                string parentElementName = null;

                var emptyElement = token.GetAncestor<XmlEmptyElementSyntax>();
                if (emptyElement != null)
                {
                    parentElementName = emptyElement.Name.LocalName.Text;
                }

                // We're writing the name of a paramref or typeparamref
                if (parentElementName == ParamRefTagName)
                {
                    items.AddRange(parameters.Select(p => CreateCompletionItem(itemSpan, p)));
                }
                else if (parentElementName == TypeParamRefTagName)
                {
                    items.AddRange(typeParameters.Select(t => CreateCompletionItem(itemSpan, t)));
                }

                return items;
            }

            RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, ParamTagName));
            RemoveExistingTags(trivia, typeParameters, x => AttributeSelector(x, TypeParamTagName));

            items.AddRange(parameters.Select(p => CreateCompletionItem(itemSpan, FormatParameter(ParamTagName, p))));
            items.AddRange(typeParameters.Select(t => CreateCompletionItem(itemSpan, FormatParameter(TypeParamTagName, t))));

            // Provide a return completion item in case the function returns something
            var returns = true;

            foreach (var node in trivia.Content)
            {
                var element = node as XmlElementSyntax;
                if (element != null && !element.StartTag.IsMissing && !element.EndTag.IsMissing)
                {
                    var startTag = element.StartTag;

                    if (startTag.Name.LocalName.ValueText == ReturnsTagName)
                    {
                        returns = false;
                        break;
                    }
                }
            }

            if (returns && !symbol.ReturnsVoid)
            {
                items.Add(CreateCompletionItem(itemSpan, ReturnsTagName));
            }

            return items;
        }
 private static bool HasAnyCheckedTypeParameter(IMethodSymbol method)
 {
     return(method.GetParameters().Any(parameter => parameter.Type.IsAny(checkedTypes)));
 }
Example #15
0
 // must have same number of arguments + 1 (the argument that should be added) OR is params argument
 public static bool IsCompatibleOverload(InvocationExpressionSyntax invocation, IMethodSymbol m) =>
 (m.GetParameters().Count() - invocation.ArgumentList.Arguments.Count == 1) ||
 (m.GetParameters().Any() && m.GetParameters().Last().IsParams);
        public static IMethodSymbol OverrideMethod(
            this ISyntaxFactoryService codeFactory,
            IMethodSymbol overriddenMethod,
            SymbolModifiers modifiers,
            INamedTypeSymbol newContainingType,
            Document newDocument,
            CancellationToken cancellationToken)
        {
            // Abstract: Throw not implemented
            if (overriddenMethod.IsAbstract)
            {
                return CodeGenerationSymbolFactory.CreateMethodSymbol(
                    overriddenMethod,
                    accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
                    modifiers: modifiers,
                    statements: new[] { codeFactory.CreateThrowNotImplementStatement(newDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken)) });
            }
            else
            {
                // Otherwise, call the base method with the same parameters
                var typeParams = overriddenMethod.GetTypeArguments();
                var body = codeFactory.CreateInvocationExpression(
                    codeFactory.CreateMemberAccessExpression(codeFactory.CreateBaseExpression(),
                    typeParams.IsDefaultOrEmpty
                        ? codeFactory.CreateIdentifierName(overriddenMethod.Name)
                        : codeFactory.CreateGenericName(overriddenMethod.Name, typeParams)),
                    codeFactory.CreateArguments(overriddenMethod.GetParameters()));

                return CodeGenerationSymbolFactory.CreateMethodSymbol(
                    method: overriddenMethod,
                    accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
                    modifiers: modifiers,
                    statements: ((IMethodSymbol)overriddenMethod).ReturnsVoid
                        ? new SyntaxNode[] { codeFactory.CreateExpressionStatement(body) }
                        : new SyntaxNode[] { codeFactory.CreateReturnStatement(body) });
            }
        }
        private IEnumerable <CompletionItem> GetTagsForMethod(
            IMethodSymbol symbol, DocumentationCommentTriviaSyntax trivia, SyntaxToken token)
        {
            var items = new List <CompletionItem>();

            var parameters     = symbol.GetParameters().Select(p => p.Name).ToSet();
            var typeParameters = symbol.TypeParameters.Select(t => t.Name).ToSet();

            // User is trying to write a name, try to suggest only names.
            if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) ||
                (token.Parent.IsKind(SyntaxKind.IdentifierName) && token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute)))
            {
                string parentElementName = null;

                var emptyElement = token.GetAncestor <XmlEmptyElementSyntax>();
                if (emptyElement != null)
                {
                    parentElementName = emptyElement.Name.LocalName.Text;
                }

                // We're writing the name of a paramref or typeparamref
                if (parentElementName == ParamRefTagName)
                {
                    items.AddRange(parameters.Select(CreateCompletionItem));
                }
                else if (parentElementName == TypeParamRefTagName)
                {
                    items.AddRange(typeParameters.Select(CreateCompletionItem));
                }

                return(items);
            }

            RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, ParamTagName));
            RemoveExistingTags(trivia, typeParameters, x => AttributeSelector(x, TypeParamTagName));

            items.AddRange(parameters.Select(p => CreateCompletionItem(FormatParameter(ParamTagName, p))));
            items.AddRange(typeParameters.Select(t => CreateCompletionItem(FormatParameter(TypeParamTagName, t))));

            // Provide a return completion item in case the function returns something
            var returns = true;

            foreach (var node in trivia.Content)
            {
                var element = node as XmlElementSyntax;
                if (element != null && !element.StartTag.IsMissing && !element.EndTag.IsMissing)
                {
                    var startTag = element.StartTag;

                    if (startTag.Name.LocalName.ValueText == ReturnsTagName)
                    {
                        returns = false;
                        break;
                    }
                }
            }

            if (returns && !symbol.ReturnsVoid)
            {
                items.Add(CreateCompletionItem(ReturnsTagName));
            }

            return(items);
        }
        private IEnumerable<CompletionItem> GetTagsForMethod(IMethodSymbol symbol, TextSpan filterSpan, DocumentationCommentTriviaSyntax trivia, SyntaxToken token)
        {
            var items = new List<CompletionItem>();

            var parameters = symbol.GetParameters().Select(p => p.Name).ToSet();
            var typeParameters = symbol.TypeParameters.Select(t => t.Name).ToSet();

            // User is trying to write a name, try to suggest only names.
            if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) ||
                (token.Parent.IsKind(SyntaxKind.IdentifierName) && token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute)))
            {
                string parentElementName = null;

                var emptyElement = token.GetAncestor<XmlEmptyElementSyntax>();
                if (emptyElement != null)
                {
                    parentElementName = emptyElement.Name.LocalName.Text;
                }

                // We're writing the name of a paramref or typeparamref
                if (parentElementName == "paramref")
                {
                    items.AddRange(parameters.Select(p => new XmlDocCommentCompletionItem(this, filterSpan, p, GetCompletionItemRules())));
                }
                else if (parentElementName == "typeparamref")
                {
                    items.AddRange(typeParameters.Select(t => new XmlDocCommentCompletionItem(this, filterSpan, t, GetCompletionItemRules())));
                }

                return items;
            }

            var returns = true;

            RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, "param"));
            RemoveExistingTags(trivia, typeParameters, x => AttributeSelector(x, "typeparam"));

            foreach (var node in trivia.Content)
            {
                var element = node as XmlElementSyntax;
                if (element != null && !element.StartTag.IsMissing && !element.EndTag.IsMissing)
                {
                    var startTag = element.StartTag;

                    if (startTag.Name.LocalName.ValueText == "returns")
                    {
                        returns = false;
                        break;
                    }
                }
            }

            items.AddRange(parameters.Select(p => new XmlDocCommentCompletionItem(this, filterSpan, FormatParameter("param", p), GetCompletionItemRules())));
            items.AddRange(typeParameters.Select(t => new XmlDocCommentCompletionItem(this, filterSpan, FormatParameter("typeparam", t), GetCompletionItemRules())));

            if (returns && !symbol.ReturnsVoid)
            {
                items.Add(new XmlDocCommentCompletionItem(this, filterSpan, "returns", GetCompletionItemRules()));
            }

            return items;
        }