public static void Create(IMethodSymbol symbol, SymbolKeyWriter visitor)
            {
                Debug.Assert(symbol.Equals(symbol.ConstructedFrom));

                visitor.WriteSymbolKey(symbol.ReducedFrom);
                visitor.WriteSymbolKey(symbol.ReceiverType);
            }
            public static void Create(IMethodSymbol symbol, SymbolKeyWriter visitor)
            {
                Debug.Assert(symbol.Equals(symbol.ConstructedFrom));

                visitor.WriteString(symbol.MetadataName);
                visitor.WriteSymbolKey(symbol.ContainingSymbol);
                visitor.WriteInteger(symbol.Arity);
                visitor.WriteBoolean(symbol.PartialDefinitionPart != null);
                visitor.WriteRefKindArray(symbol.Parameters);

                // Mark that we're writing out the signature of a method.  This way if we hit a 
                // method type parameter in our parameter-list or return type, we won't recurse
                // into it, but will instead only write out the type parameter ordinal.  This
                // happens with cases like Foo<T>(T t);
                Debug.Assert(!visitor.WritingSignature);
                visitor.WritingSignature = true;

                visitor.WriteParameterTypesArray(symbol.OriginalDefinition.Parameters);

                if (symbol.MethodKind == MethodKind.Conversion)
                {
                    visitor.WriteSymbolKey(symbol.ReturnType);
                }
                else
                {
                    visitor.WriteSymbolKey(null);
                }

                // Done writing the signature.  Go back to normal mode.
                Debug.Assert(visitor.WritingSignature);
                visitor.WritingSignature = false;
            }
Example #3
0
        private void CheckName(string name, SimpleNameSyntax node)
        {
            for (int i = Nodes.Count - 1; i >= 0; i--)
            {
                NodeSymbolInfo info = Nodes[i];

                if (info.Name == name)
                {
                    if (info.Symbol == null)
                    {
                        ISymbol declaredSymbol = SemanticModel.GetDeclaredSymbol(info.Node, CancellationToken);

                        Debug.Assert(declaredSymbol != null, "");

                        if (declaredSymbol == null)
                        {
                            RemoveNodeAt(i);
                            continue;
                        }

                        info = new NodeSymbolInfo(info.Name, info.Node, declaredSymbol);

                        Nodes[i] = info;
                    }

                    ISymbol symbol = SemanticModel.GetSymbol(node, CancellationToken);

                    if (symbol == null)
                    {
                        continue;
                    }

                    if (symbol is IMethodSymbol methodSymbol)
                    {
                        symbol = methodSymbol.ReducedFrom ?? methodSymbol;
                    }

                    if (info.Symbol.Equals(symbol.OriginalDefinition) &&
                        _containingMethodSymbol?.Equals(symbol.OriginalDefinition) != true)
                    {
                        RemoveNodeAt(i);
                    }
                }
            }
        }
        /// <summary>
        /// Check whether given overloads has any overload whose parameters has the given type as its parameter type.
        /// </summary>
        public static bool HasOverloadWithParameterOfType(this IEnumerable <IMethodSymbol> overloads, IMethodSymbol self, INamedTypeSymbol type, CancellationToken cancellationToken)
        {
            foreach (var overload in overloads)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (self?.Equals(overload) == true)
                {
                    continue;
                }

                if (overload.Parameters.ContainsParameterOfType(type))
                {
                    return(true);
                }
            }

            return(false);
        }
 private static bool IsMethodUsedAsEventHandlerFunctionOrActionInExpression(IMethodSymbol methodSymbol, ExpressionSyntax expression, SemanticModel semanticModel)
 {
     return !expression.IsKind(SyntaxKind.InvocationExpression) &&
         IsStandaloneExpression(expression) &&
         methodSymbol.Equals(semanticModel.GetSymbolInfo(expression).Symbol?.OriginalDefinition);
 }
        public static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context)
        {
            var methodDeclaration = (MethodDeclarationSyntax)context.Node;

            if (methodDeclaration.ContainsDirectives)
            {
                return;
            }

            if (methodDeclaration.ContainsDiagnostics)
            {
                return;
            }

            SyntaxTokenList modifiers = methodDeclaration.Modifiers;

            if (!modifiers.Contains(SyntaxKind.OverrideKeyword))
            {
                return;
            }

            if (modifiers.ContainsAny(SyntaxKind.SealedKeyword, SyntaxKind.PartialKeyword))
            {
                return;
            }

            if (methodDeclaration.AttributeLists.Any())
            {
                return;
            }

            if (methodDeclaration.HasDocumentationComment())
            {
                return;
            }

            if (!methodDeclaration.DescendantTrivia(methodDeclaration.Span).All(f => f.IsWhitespaceOrEndOfLineTrivia()))
            {
                return;
            }

            ExpressionSyntax expression = GetMethodExpression(methodDeclaration);

            if (!MemberInvocationExpression.TryCreate(expression, out MemberInvocationExpression memberInvocation))
            {
                return;
            }

            if (!memberInvocation.Expression.IsKind(SyntaxKind.BaseExpression))
            {
                return;
            }

            IMethodSymbol methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken);

            IMethodSymbol overriddenMethod = methodSymbol?.OverriddenMethod;

            if (overriddenMethod == null)
            {
                return;
            }

            ISymbol symbol = context.SemanticModel.GetSymbol(memberInvocation.Name, context.CancellationToken);

            if (!overriddenMethod.Equals(symbol))
            {
                return;
            }

            if (!CheckParameters(methodDeclaration.ParameterList, memberInvocation.ArgumentList, context.SemanticModel, context.CancellationToken))
            {
                return;
            }

            if (!CheckDefaultValues(methodSymbol.Parameters, overriddenMethod.Parameters))
            {
                return;
            }

            context.ReportDiagnostic(
                DiagnosticDescriptors.RemoveRedundantOverridingMember,
                methodDeclaration,
                methodDeclaration.GetTitle());
        }
        /// <summary>
        /// Checks if the given method is an implementation of the given interface method
        /// Substituted with the given typeargument.
        /// </summary>
        public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol typeArgument, INamedTypeSymbol interfaceType, string interfaceMethodName)
        {
            INamedTypeSymbol constructedInterface = typeArgument != null?interfaceType?.Construct(typeArgument) : interfaceType;

            return(constructedInterface?.GetMembers(interfaceMethodName).Single() is IMethodSymbol interfaceMethod && method.Equals(method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod)));
        }
            private bool CheckOverloadsContainUriParameters(SemanticModel model, IMethodSymbol method, SyntaxNode node, CancellationToken cancellationToken)
            {
                INamedTypeSymbol uriType = _uri;
                foreach (IMethodSymbol overload in model.GetMemberGroup(node, cancellationToken).OfType<IMethodSymbol>())
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    if (method.Equals(overload))
                    {
                        continue;
                    }

                    if (overload.Parameters.Any(p => p.Type?.Equals(uriType) == true))
                    {
                        return true;
                    }
                }

                return false;
            }
        private static bool IsMethodCandidate(IMethodSymbol methodSymbol)
        {
            if (methodSymbol.IsAbstract ||
                methodSymbol.IsVirtual ||
                methodSymbol.IsOverride)
            {
                return false;
            }

            return !methodSymbol.ContainingType
                .AllInterfaces
                .SelectMany(@interface => @interface.GetMembers().OfType<IMethodSymbol>())
                .Any(method => methodSymbol.Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(method)));
        }
        private static bool HasVisibleAlternate(INamedTypeSymbol namedType, IMethodSymbol interfaceMethod, INamedTypeSymbol iDisposableTypeSymbol)
        {
            foreach (INamedTypeSymbol type in namedType.GetBaseTypesAndThis())
            {
                foreach (IMethodSymbol method in type.GetMembers(interfaceMethod.Name).OfType<IMethodSymbol>())
                {
                    if (method.GetResultantVisibility() == SymbolVisibility.Public)
                    {
                        return true;
                    }
                }
            }

            // This rule does not report a violation for an explicit implementation of IDisposable.Dispose when an externally visible Close() or System.IDisposable.Dispose(Boolean) method is provided.
            return interfaceMethod.Equals("Dispose") &&
                interfaceMethod.ContainingType.Equals(iDisposableTypeSymbol) &&
                namedType.GetBaseTypesAndThis().Any(t =>
                    t.GetMembers("Close").OfType<IMethodSymbol>().Any(m =>
                        m.GetResultantVisibility() == SymbolVisibility.Public));
        }
Example #11
0
        private void AnalyzeSyntax(SyntaxNodeAnalysisContext context, IMethodSymbol referenceEqualsMethod)
        {
            var cancellationToken = context.CancellationToken;

            var semanticModel = context.SemanticModel;
            var syntaxTree    = semanticModel.SyntaxTree;

            if (!IsLanguageVersionSupported(syntaxTree.Options))
            {
                return;
            }

            var optionSet = context.Options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult();

            if (optionSet == null)
            {
                return;
            }

            var option = optionSet.GetOption(CodeStyleOptions.PreferIsNullCheckOverReferenceEqualityMethod, semanticModel.Language);

            if (!option.Value)
            {
                return;
            }

            var invocation  = context.Node;
            var syntaxFacts = GetSyntaxFactsService();

            var expression = syntaxFacts.GetExpressionOfInvocationExpression(invocation);
            var nameNode   = syntaxFacts.IsIdentifierName(expression)
                ? expression
                : syntaxFacts.IsSimpleMemberAccessExpression(expression)
                    ? syntaxFacts.GetNameOfMemberAccessExpression(expression)
                    : null;

            if (!syntaxFacts.IsIdentifierName(nameNode))
            {
                return;
            }

            syntaxFacts.GetNameAndArityOfSimpleName(nameNode, out var name, out _);
            if (!syntaxFacts.StringComparer.Equals(name, nameof(ReferenceEquals)))
            {
                return;
            }

            var arguments = syntaxFacts.GetArgumentsOfInvocationExpression(invocation);

            if (arguments.Count != 2)
            {
                return;
            }

            if (!MatchesPattern(syntaxFacts, arguments[0], arguments[1]) &&
                !MatchesPattern(syntaxFacts, arguments[1], arguments[0]))
            {
                return;
            }

            var symbol = semanticModel.GetSymbolInfo(invocation, cancellationToken).Symbol;

            if (!referenceEqualsMethod.Equals(symbol))
            {
                return;
            }

            var properties = ImmutableDictionary <string, string> .Empty.Add(
                UseIsNullConstants.Kind, UseIsNullConstants.ReferenceEqualsKey);

            var genericParameterSymbol = GetGenericParameterSymbol(syntaxFacts, semanticModel, arguments[0], arguments[1], cancellationToken);

            if (genericParameterSymbol != null)
            {
                if (genericParameterSymbol.HasValueTypeConstraint)
                {
                    // 'is null' would generate error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
                    // '== null' would generate error CS0019: Operator '==' cannot be applied to operands of type 'T' and '<null>'
                    // 'Is Nothing' would generate error BC30020: 'Is' operator does not accept operands of type 'T'. Operands must be reference or nullable types.
                    return;
                }

                if (!genericParameterSymbol.HasReferenceTypeConstraint)
                {
                    // Needs special casing for C# as long as
                    // https://github.com/dotnet/csharplang/issues/1284
                    // is not implemented.
                    properties = properties.Add(AbstractUseIsNullCheckForReferenceEqualsCodeFixProvider.UnconstrainedGeneric, "");
                }
            }

            var additionalLocations = ImmutableArray.Create(invocation.GetLocation());

            var negated = syntaxFacts.IsLogicalNotExpression(invocation.Parent);

            if (negated)
            {
                properties = properties.Add(AbstractUseIsNullCheckForReferenceEqualsCodeFixProvider.Negated, "");
            }

            var severity = option.Notification.Severity;

            context.ReportDiagnostic(
                DiagnosticHelper.Create(
                    Descriptor, nameNode.GetLocation(),
                    severity,
                    additionalLocations, properties));
        }
 private static bool MethodIsDisposeImplementation(IMethodSymbol methodSymbol, IMethodSymbol disposeMethod)
 {
     return methodSymbol.Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(disposeMethod));
 }
Example #13
0
        /// <summary>
        /// Checks if the given method is an implementation of the given interface method
        /// Substituted with the given typeargument.
        /// </summary>
        public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol?typeArgument, [NotNullWhen(returnValue: true)] INamedTypeSymbol?interfaceType, string interfaceMethodName)
        {
            INamedTypeSymbol?constructedInterface = typeArgument != null?interfaceType?.Construct(typeArgument) : interfaceType;

            return(constructedInterface?.GetMembers(interfaceMethodName).FirstOrDefault() is IMethodSymbol interfaceMethod && method.Equals(method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod)));
        }
 public void PopMethod(IMethodSymbol method)
 {
     Contract.ThrowIfTrue(_methodSymbolStack.Count == 0);
     Contract.ThrowIfFalse(method.Equals(_methodSymbolStack.Last()));
     _methodSymbolStack.RemoveAt(_methodSymbolStack.Count - 1);
 }
Example #15
0
        private static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context)
        {
            var methodDeclaration = (MethodDeclarationSyntax)context.Node;

            if (methodDeclaration.ContainsDirectives)
            {
                return;
            }

            if (methodDeclaration.ContainsDiagnostics)
            {
                return;
            }

            if (methodDeclaration.AttributeLists.Any())
            {
                return;
            }

            if (!CheckModifiers(methodDeclaration.Modifiers))
            {
                return;
            }

            if (methodDeclaration.HasDocumentationComment())
            {
                return;
            }

            if (!methodDeclaration.DescendantTrivia(methodDeclaration.Span).All(f => f.IsWhitespaceOrEndOfLineTrivia()))
            {
                return;
            }

            ExpressionSyntax expression = GetMethodExpression(methodDeclaration);

            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(expression);

            if (!invocationInfo.Success)
            {
                return;
            }

            if (invocationInfo.Expression.Kind() != SyntaxKind.BaseExpression)
            {
                return;
            }

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, cancellationToken);

            if (methodSymbol == null)
            {
                return;
            }

            IMethodSymbol overriddenMethod = methodSymbol.OverriddenMethod;

            if (overriddenMethod == null)
            {
                return;
            }

            ISymbol symbol = semanticModel.GetSymbol(invocationInfo.Name, cancellationToken);

            if (!overriddenMethod.Equals(symbol))
            {
                return;
            }

            if (!CheckParameters(methodDeclaration.ParameterList, invocationInfo.ArgumentList, semanticModel, cancellationToken))
            {
                return;
            }

            if (!CheckDefaultValues(methodSymbol.Parameters, overriddenMethod.Parameters))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context,
                                               DiagnosticDescriptors.RemoveRedundantOverridingMember,
                                               methodDeclaration,
                                               CSharpFacts.GetTitle(methodDeclaration));
        }
 private static bool IsInterfaceMethodImplementation(IMethodSymbol method, IMethodSymbol interfaceMethod)
 {
     return interfaceMethod != null && method.Equals(method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod));
 }
 private static bool IsInterfaceMethodImplementation(IMethodSymbol method, IMethodSymbol interfaceMethod)
 {
     return(interfaceMethod != null && method.Equals(method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod)));
 }
        private bool IsIEqualityComparerGetHashCodeInterfaceImplementation(IMethodSymbol method, IMethodSymbol iEqualityComparerGetHashCodeInterfaceMethod)
        {
            if (iEqualityComparerGetHashCodeInterfaceMethod == null)
            {
                return false;
            }

            INamedTypeSymbol iEqualityComparerInterfaceType = iEqualityComparerGetHashCodeInterfaceMethod.ContainingType;

            foreach (INamedTypeSymbol interfaceType in method.ContainingType.AllInterfaces.Where(
                ifaceType => iEqualityComparerInterfaceType.Equals(ifaceType.ConstructedFrom)))
            {
                foreach (var unboundGenericInterfaceMethod in
                    interfaceType.GetMembers(iEqualityComparerGetHashCodeInterfaceMethod.Name).OfType<IMethodSymbol>())
                {
                    var implementingMethod = method.ContainingType.FindImplementationForInterfaceMember(unboundGenericInterfaceMethod) as IMethodSymbol;
                    if (method.Equals(implementingMethod))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
Example #19
0
 private static bool IsConstructedFromSelf(IMethodSymbol symbol)
 => symbol.Equals(symbol.ConstructedFrom);
Example #20
0
        private void VisitSimpleName(SimpleNameSyntax node, string name)
        {
            for (int i = Nodes.Count - 1; i >= 0; i--)
            {
                NodeSymbolInfo info = Nodes[i];

                if (info.Name == name)
                {
                    if (info.Symbol == null)
                    {
                        ISymbol declaredSymbol = SemanticModel.GetDeclaredSymbol(info.Node, CancellationToken);

                        Debug.Assert(declaredSymbol != null, "");

                        if (declaredSymbol == null)
                        {
                            RemoveNodeAt(i);
                            continue;
                        }

                        info = new NodeSymbolInfo(info.Name, info.Node, declaredSymbol);

                        Nodes[i] = info;
                    }

                    SymbolInfo symbolInfo = SemanticModel.GetSymbolInfo(node, CancellationToken);

                    if (symbolInfo.Symbol != null)
                    {
                        ISymbol symbol = symbolInfo.Symbol;

                        if (symbol.Kind == SymbolKind.Method)
                        {
                            var methodSymbol = ((IMethodSymbol)symbol);

                            if (methodSymbol.MethodKind == MethodKind.ReducedExtension)
                            {
                                symbol = methodSymbol.ReducedFrom;
                            }
                        }

                        symbol = symbol.OriginalDefinition;

                        if (info.Symbol.Equals(symbol) &&
                            _containingMethodSymbol?.Equals(symbol) != true)
                        {
                            RemoveNodeAt(i);
                        }
                    }
                    else if (symbolInfo.CandidateReason == CandidateReason.MemberGroup)
                    {
                        ImmutableArray <ISymbol> candidateSymbols = symbolInfo.CandidateSymbols;

                        for (int j = 0; j < candidateSymbols.Length; j++)
                        {
                            ISymbol symbol = candidateSymbols[j].OriginalDefinition;

                            if (info.Symbol.Equals(symbol) &&
                                _containingMethodSymbol?.Equals(symbol) != true)
                            {
                                RemoveNodeAt(i);
                            }
                        }
                    }
                }
            }
        }
Example #21
0
            public void Analyze(OperationAnalysisContext context, ISymbol owningSymbol)
            {
                if (context.Operation.IsInvalid)
                {
                    // not interested in invalid expression
                    return;
                }

                var           invocation = (IInvocationExpression)context.Operation;
                IMethodSymbol method     = invocation.TargetMethod;

                SyntaxNode node = _expressionGetter(context.Operation.Syntax);

                if (node == null)
                {
                    // we don't have right expression node to check overloads
                    return;
                }

                // REVIEW: why IOperation doesn't contain things like compilation and semantic model?
                //         it seems wierd that I need to do this to get thsoe.
                SemanticModel model = _compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree);

                // due to limitation of using "this" in lambda in struct
                INamedTypeSymbol stringType = _string;
                IEnumerable <IParameterSymbol> stringParameters = method.Parameters.Where(p => p.Type?.Equals(stringType) == true);

                if (!stringParameters.Any())
                {
                    // no string parameter. not interested.
                    return;
                }

                // now do cheap string check whether those string parameter contains uri word list we are looking for.
                if (!CheckStringParametersContainUriWords(stringParameters, context.CancellationToken))
                {
                    // no string parameter that contains what we are looking for.
                    return;
                }

                // now we make sure we actually have overloads that contains uri type parameter
                if (!CheckOverloadsContainUriParameters(model, method, node, context.CancellationToken))
                {
                    // no overload that contains uri as parameter
                    return;
                }

                // now we do more expensive word parsing to find exact parameter that contains url in parameter name
                var indicesSet = new HashSet <int>(GetParameterIndices(method, GetStringParametersThatContainsUriWords(stringParameters, context.CancellationToken), context.CancellationToken));

                // now we search exact match. this is exactly same behavior as old FxCop
                foreach (IMethodSymbol overload in model.GetMemberGroup(node, context.CancellationToken).OfType <IMethodSymbol>())
                {
                    context.CancellationToken.ThrowIfCancellationRequested();

                    if (method.Equals(overload) || overload.Parameters.Length != method.Parameters.Length)
                    {
                        // either itself, or signature is not same
                        continue;
                    }

                    if (!CheckParameterTypes(method, overload, Enumerable.Range(0, method.Parameters.Length).Where(i => !indicesSet.Contains(i)), context.CancellationToken))
                    {
                        // check whether remaining parameters match existing types, otherwise, we are not interested
                        continue;
                    }

                    // original FxCop implementation doesnt account for case where original method call contains
                    // 2+ string uri parameters that has overload with matching uri parameters. original implementation works
                    // when there is exactly 1 parameter having matching uri overload. this implementation follow that.
                    foreach (int index in indicesSet)
                    {
                        // check other string uri parameters matches original type
                        if (!CheckParameterTypes(method, overload, indicesSet.Where(i => i != index), context.CancellationToken))
                        {
                            continue;
                        }

                        // okay all other type match. check the main one
                        if (overload.Parameters[index].Type?.Equals(_uri) == true)
                        {
                            context.ReportDiagnostic(node.CreateDiagnostic(Rule, owningSymbol.ToDisplayString(s_symbolDisplayFormat), overload.ToDisplayString(s_symbolDisplayFormat), method.ToDisplayString(s_symbolDisplayFormat)));

                            // we no longer interested in this overload. there can be only 1 match
                            break;
                        }
                    }
                }
            }
        private static bool MethodMightImplementDispose(IMethodSymbol declaredMethodSymbol)
        {
            var containingType = declaredMethodSymbol.ContainingType;

            if (containingType.BaseType != null && containingType.BaseType.Kind == SymbolKind.ErrorType)
            {
                return true;
            }

            var interfaces = containingType.AllInterfaces;
            foreach (var @interface in interfaces)
            {
                if (@interface.Kind == SymbolKind.ErrorType)
                {
                    return true;
                }

                var interfaceMethods = @interface.GetMembers().OfType<IMethodSymbol>();
                foreach (var interfaceMethod in interfaceMethods)
                {
                    if (declaredMethodSymbol.Equals(containingType.FindImplementationForInterfaceMember(interfaceMethod)))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
Example #23
0
 private static bool MethodIsDisposeImplementation(IMethodSymbol methodSymbol, IMethodSymbol disposeMethod)
 {
     return(methodSymbol.Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(disposeMethod)));
 }
 private static bool IsPrivateAndUsedAsMethodGroup(MethodDeclarationSyntax method, IMethodSymbol methodSymbol, SemanticModel semanticModel)
 {
     if (methodSymbol.DeclaredAccessibility != Accessibility.Private) return false;
     var parentType = method.Parent;
     var allTokens = parentType.DescendantTokens();
     var tokensThatMatch = from t in allTokens
                           let text = t.Text
                           where text == method.Identifier.Text
                           select t;
     foreach (var token in tokensThatMatch)
     {
         var nodeSymbol = semanticModel.GetSymbolInfo(token.Parent).Symbol;
         if (methodSymbol.Equals(nodeSymbol)) return true;
     }
     return false;
 }
 private static bool IsMethodUsedAsEventHandlerFunctionOrActionInExpression(IMethodSymbol methodSymbol, ExpressionSyntax expression, SemanticModel semanticModel)
 {
     return(!expression.IsKind(SyntaxKind.InvocationExpression) &&
            IsStandaloneExpression(expression) &&
            methodSymbol.Equals(semanticModel.GetSymbolInfo(expression).Symbol?.OriginalDefinition));
 }
 private static bool IsConstructedFromSelf(IMethodSymbol symbol)
 {
     return(symbol.Equals(symbol.ConstructedFrom));
 }
Example #27
0
        // Can be removed if https://github.com/dotnet/roslyn/issues/67 gets resolved
        // Modeled after Sandcastle implementation: http://tunnelvisionlabs.github.io/SHFB/docs-master/XMLCommentsGuide/html/86453FFB-B978-4A2A-9EB5-70E118CA8073.htm
        private void ProcessInheritDoc(XElement root, ISymbol currentSymbol, List <XElement> inheritDocElements, HashSet <string> inheritedSymbolCommentIds)
        {
            if (inheritDocElements.Count > 0)
            {
                // Gather the documents (first in the list takes precedence)
                List <ISymbol> inheritedSymbols = new List <ISymbol>();
                foreach (XElement inheritDocElement in inheritDocElements)
                {
                    // Remove from the parent
                    inheritDocElement.Remove();

                    // Locate the appropriate symbol
                    string inheritDocElementCref = inheritDocElement.Attribute("cref")?.Value;
                    if (inheritDocElementCref == null && inheritedSymbolCommentIds.Add(currentSymbol.GetDocumentationCommentId()))
                    {
                        INamedTypeSymbol currentTypeSymbol   = currentSymbol as INamedTypeSymbol;
                        IMethodSymbol    currentMethodSymbol = currentSymbol as IMethodSymbol;
                        if (currentTypeSymbol != null)
                        {
                            // Types and interfaces, inherit from all base types
                            List <INamedTypeSymbol> baseTypeSymbols = AnalyzeSymbolVisitor.GetBaseTypes(currentTypeSymbol)
                                                                      .Where(x => inheritedSymbolCommentIds.Add(x.GetDocumentationCommentId()))
                                                                      .ToList();
                            if (baseTypeSymbols.Count > 0)
                            {
                                inheritedSymbols.AddRange(baseTypeSymbols);
                            }

                            // Then inherit from all interfaces
                            List <INamedTypeSymbol> interfaceSymbols = currentTypeSymbol.AllInterfaces
                                                                       .Where(x => inheritedSymbolCommentIds.Add(x.GetDocumentationCommentId()))
                                                                       .ToList();
                            if (interfaceSymbols.Count > 0)
                            {
                                inheritedSymbols.AddRange(interfaceSymbols);
                            }
                        }
                        else if (currentMethodSymbol != null && currentMethodSymbol.Name == currentMethodSymbol.ContainingType.Name)
                        {
                            // Constructor, check base type constructors for the same signature
                            string signature = AnalyzeSymbolVisitor.GetFullName(currentMethodSymbol);
                            signature = signature.Substring(signature.IndexOf('('));
                            foreach (INamedTypeSymbol baseTypeSymbol in AnalyzeSymbolVisitor.GetBaseTypes(currentMethodSymbol.ContainingType))
                            {
                                foreach (IMethodSymbol constructorSymbol in baseTypeSymbol.Constructors.Where(x => !x.IsImplicitlyDeclared))
                                {
                                    string constructorSignature = AnalyzeSymbolVisitor.GetFullName(constructorSymbol);
                                    constructorSignature = constructorSignature.Substring(constructorSignature.IndexOf('('));
                                    if (signature == constructorSignature &&
                                        inheritedSymbolCommentIds.Add(constructorSymbol.GetDocumentationCommentId()))
                                    {
                                        inheritedSymbols.Add(constructorSymbol);
                                    }
                                }
                            }
                        }
                        else if (currentMethodSymbol != null)
                        {
                            IMethodSymbol overriddenMethodSymbol = null;
                            if (currentMethodSymbol.IsOverride)
                            {
                                // Override, get overridden method
                                overriddenMethodSymbol = currentMethodSymbol.OverriddenMethod;
                                if (overriddenMethodSymbol != null &&
                                    inheritedSymbolCommentIds.Add(overriddenMethodSymbol.GetDocumentationCommentId()))
                                {
                                    inheritedSymbols.Add(overriddenMethodSymbol);
                                }
                            }

                            // Check if this is an interface implementation
                            IMethodSymbol interfaceMethodSymbol = currentMethodSymbol.ContainingType.AllInterfaces
                                                                  .SelectMany(x => x.GetMembers().OfType <IMethodSymbol>())
                                                                  .FirstOrDefault(x =>
                            {
                                ISymbol implementationSymbol = currentSymbol.ContainingType.FindImplementationForInterfaceMember(x);
                                return(currentSymbol.Equals(implementationSymbol) ||
                                       (overriddenMethodSymbol != null && overriddenMethodSymbol.Equals(implementationSymbol)));
                            });
                            if (interfaceMethodSymbol != null &&
                                inheritedSymbolCommentIds.Add(interfaceMethodSymbol.GetDocumentationCommentId()))
                            {
                                inheritedSymbols.Add(interfaceMethodSymbol);
                            }
                        }
                    }
                    else if (inheritDocElementCref != null)
                    {
                        // Explicit cref
                        if (inheritedSymbolCommentIds.Add(inheritDocElementCref))
                        {
                            ISymbol inheritedSymbol = DocumentationCommentId.GetFirstSymbolForDeclarationId(inheritDocElementCref, _compilation);
                            if (inheritedSymbol != null)
                            {
                                inheritedSymbols.Add(inheritedSymbol);
                            }
                        }
                    }
                }

                // Add the inherited comments
                foreach (ISymbol inheritedSymbol in inheritedSymbols)
                {
                    string inheritedXml = inheritedSymbol.GetDocumentationCommentXml(expandIncludes: true);
                    if (!string.IsNullOrEmpty(inheritedXml))
                    {
                        XElement inheritedRoot = GetRootElement(inheritedXml);
                        if (inheritedRoot != null)
                        {
                            // Inherit elements other than <inheritdoc>
                            List <XElement> inheritedInheritDocElements = new List <XElement>();
                            foreach (XElement inheritedElement in inheritedRoot.Elements())
                            {
                                if (inheritedElement.Name == "inheritdoc")
                                {
                                    inheritedInheritDocElements.Add(inheritedElement);
                                }
                                else
                                {
                                    string inheritedElementCref = inheritedElement.Attribute("cref")?.Value;
                                    string inheritedElementName = inheritedElement.Attribute("name")?.Value;
                                    bool   inherit = true;
                                    foreach (XElement rootElement in root.Elements(inheritedElement.Name))
                                    {
                                        if (inheritedElementCref == null && inheritedElementName == null)
                                        {
                                            // Don't inherit if the name is the same and there's no distinguishing attributes
                                            inherit = false;
                                            break;
                                        }
                                        if (inheritedElementCref != null && inheritedElementCref == rootElement.Attribute("cref")?.Value)
                                        {
                                            // Don't inherit if the cref attribute is the same
                                            inherit = false;
                                            break;
                                        }
                                        if (inheritedElementName != null && inheritedElementName == rootElement.Attribute("name")?.Value)
                                        {
                                            // Don't inherit if the name attribute is the same
                                            inherit = false;
                                            break;
                                        }
                                    }
                                    if (inherit)
                                    {
                                        root.Add(inheritedElement);
                                    }
                                }
                            }

                            // Recursively inherit <inheritdoc>
                            if (inheritedInheritDocElements.Count > 0)
                            {
                                ProcessInheritDoc(root, inheritedSymbol, inheritedInheritDocElements, inheritedSymbolCommentIds);
                            }
                        }
                    }
                }
            }
        }