protected override bool TryInitializeState(
            Document document, SemanticModel model, SyntaxNode node, CancellationToken cancellationToken,
            out INamedTypeSymbol classType, out INamedTypeSymbol abstractClassType)
        {
            var baseClassNode = node as TypeSyntax;
            if (baseClassNode != null && baseClassNode.Parent is BaseTypeSyntax &&
                baseClassNode.Parent.IsParentKind(SyntaxKind.BaseList) &&
                ((BaseTypeSyntax)baseClassNode.Parent).Type == baseClassNode)
            {
                if (baseClassNode.Parent.Parent.IsParentKind(SyntaxKind.ClassDeclaration))
                {
                    abstractClassType = model.GetTypeInfo(baseClassNode, cancellationToken).Type as INamedTypeSymbol;
                    cancellationToken.ThrowIfCancellationRequested();

                    if (abstractClassType.IsAbstractClass())
                    {
                        var classDecl = baseClassNode.Parent.Parent.Parent as ClassDeclarationSyntax;
                        classType = model.GetDeclaredSymbol(classDecl, cancellationToken) as INamedTypeSymbol;

                        return classType != null && abstractClassType != null;
                    }
                }
            }

            classType = null;
            abstractClassType = null;
            return false;
        }
 public void AnalyzeCodeBlock(SyntaxNode codeBlock, ISymbol ownerSymbol, SemanticModel semanticModel, Action<Diagnostic> addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken)
 {
     if (IsEmptyFinalizer(codeBlock, semanticModel))
     {
         addDiagnostic(ownerSymbol.CreateDiagnostic(Rule));
     }
 }
        private IEnumerable<SignatureHelpParameter> GetDelegateTypeParameters(IMethodSymbol invokeMethod, SemanticModel semanticModel, int position, CancellationToken cancellationToken)
        {
            const string TargetName = "target";

            var parts = new List<SymbolDisplayPart>();
            parts.AddRange(invokeMethod.ReturnType.ToMinimalDisplayParts(semanticModel, position));
            parts.Add(Space());
            parts.Add(Punctuation(SyntaxKind.OpenParenToken));

            var first = true;
            foreach (var parameter in invokeMethod.Parameters)
            {
                if (!first)
                {
                    parts.Add(Punctuation(SyntaxKind.CommaToken));
                    parts.Add(Space());
                }

                first = false;
                parts.AddRange(parameter.Type.ToMinimalDisplayParts(semanticModel, position));
            }

            parts.Add(Punctuation(SyntaxKind.CloseParenToken));
            parts.Add(Space());
            parts.Add(new SymbolDisplayPart(SymbolDisplayPartKind.ParameterName, null, TargetName));

            yield return new SignatureHelpParameter(
                TargetName,
                isOptional: false,
                documentationFactory: null,
                displayParts: parts);
        }
示例#4
0
 public Walker(SemanticModel semanticModel, SemanticMap map, CancellationToken cancellationToken) :
     base(SyntaxWalkerDepth.Token)
 {
     _semanticModel = semanticModel;
     _map = map;
     _cancellationToken = cancellationToken;
 }
        private IEnumerable<SignatureHelpItem> GetDelegateInvokeItems(
            InvocationExpressionSyntax invocationExpression, SemanticModel semanticModel, ISymbolDisplayService symbolDisplayService, IAnonymousTypeDisplayService anonymousTypeDisplayService,
            IDocumentationCommentFormattingService documentationCommentFormattingService, ISymbol within, INamedTypeSymbol delegateType, CancellationToken cancellationToken)
        {
            var invokeMethod = delegateType.DelegateInvokeMethod;
            if (invokeMethod == null)
            {
                return null;
            }

            // Events can only be invoked directly from the class they were declared in.
            var expressionSymbol = semanticModel.GetSymbolInfo(invocationExpression.Expression, cancellationToken).GetAnySymbol();
            if (expressionSymbol.IsKind(SymbolKind.Event) &&
                !expressionSymbol.ContainingType.OriginalDefinition.Equals(within.OriginalDefinition))
            {
                return null;
            }

            var position = invocationExpression.SpanStart;
            var item = CreateItem(
                invokeMethod, semanticModel, position,
                symbolDisplayService, anonymousTypeDisplayService,
                isVariadic: invokeMethod.IsParams(),
                documentation: SpecializedCollections.EmptyEnumerable<SymbolDisplayPart>(),
                prefixParts: GetDelegateInvokePreambleParts(invokeMethod, semanticModel, position),
                separatorParts: GetSeparatorParts(),
                suffixParts: GetDelegateInvokePostambleParts(),
                parameters: GetDelegateInvokeParameters(invokeMethod, semanticModel, position, documentationCommentFormattingService, cancellationToken));

            return SpecializedCollections.SingletonEnumerable(item);
        }
 public bool IsExpressionContext(SemanticModel semanticModel, int position, CancellationToken cancellationToken)
 {
     return semanticModel.SyntaxTree.IsExpressionContext(
         position,
         semanticModel.SyntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken),
         attributes: true, cancellationToken: cancellationToken, semanticModelOpt: semanticModel);
 }
        private IEnumerable<SignatureHelpItem> GetDelegateTypeConstructors(
            ObjectCreationExpressionSyntax objectCreationExpression,
            SemanticModel semanticModel,
            ISymbolDisplayService symbolDisplayService,
            IAnonymousTypeDisplayService anonymousTypeDisplayService,
            INamedTypeSymbol delegateType,
            INamedTypeSymbol containingType,
            CancellationToken cancellationToken)
        {
            var invokeMethod = delegateType.DelegateInvokeMethod;
            if (invokeMethod == null)
            {
                return null;
            }

            var position = objectCreationExpression.SpanStart;
            var item = CreateItem(
                invokeMethod, semanticModel, position,
                symbolDisplayService, anonymousTypeDisplayService,
                isVariadic: false,
                documentationFactory: null,
                prefixParts: GetDelegateTypePreambleParts(invokeMethod, semanticModel, position),
                separatorParts: GetSeparatorParts(),
                suffixParts: GetDelegateTypePostambleParts(invokeMethod),
                parameters: GetDelegateTypeParameters(invokeMethod, semanticModel, position, cancellationToken));

            return SpecializedCollections.SingletonEnumerable(item);
        }
示例#8
0
        public ICodeBlockEndedAnalyzer OnCodeBlockStarted(SyntaxNode codeBlock, ISymbol ownerSymbol, SemanticModel semanticModel, Action<Diagnostic> addDiagnostic, CancellationToken cancellationToken)
        {
            var methodSymbol = ownerSymbol as IMethodSymbol;

            if (methodSymbol == null ||
                methodSymbol.ReturnsVoid ||
                methodSymbol.ReturnType.Kind == SymbolKind.ArrayType ||
                methodSymbol.Parameters.Length > 0 ||
                !(methodSymbol.DeclaredAccessibility == Accessibility.Public || methodSymbol.DeclaredAccessibility == Accessibility.Protected) ||
                methodSymbol.IsAccessorMethod() ||
                !IsPropertyLikeName(methodSymbol.Name))
            {
                return null;
            }

            // Fxcop has a few additional checks to reduce the noise for this diagnostic:
            // Ensure that the method is non-generic, non-virtual/override, has no overloads and doesn't have special names: 'GetHashCode' or 'GetEnumerator'.
            // Also avoid generating this diagnostic if the method body has any invocation expressions.
            if (methodSymbol.IsGenericMethod ||
                methodSymbol.IsVirtual ||
                methodSymbol.IsOverride ||
                methodSymbol.ContainingType.GetMembers(methodSymbol.Name).Length > 1 ||
                methodSymbol.Name == GetHashCodeName ||
                methodSymbol.Name == GetEnumeratorName)
            {
                return null;
            }

            return GetCodeBlockEndedAnalyzer();
        }
        public static bool AreSemanticallyEquivalent(
            SemanticModel semanticModel1,
            SemanticModel semanticModel2,
            SyntaxNode node1,
            SyntaxNode node2,
            Func<SyntaxNode, bool> predicate = null)
        {
            // First check for syntactic equivalency.  If two nodes aren't structurally equivalent,
            // then they're not semantically equivalent.
            if (node1 == null && node2 == null)
            {
                return true;
            }

            if (node1 == null || node2 == null)
            {
                return false;
            }

            if (!node1.IsEquivalentTo(node2, topLevel: false))
            {
                return false;
            }

            // From this point on we can assume the tree structure is the same.  So no need to check
            // kinds, child counts or token contents.
            return AreSemanticallyEquivalentWorker(
                semanticModel1, semanticModel2, node1, node2, predicate);
        }
示例#10
0
        /// <summary>
        /// Analyzes if type information is obvious to the reader by simply looking at the assignment expression.
        /// </summary>
        /// <remarks>
        /// <paramref name="typeInDeclaration"/> accepts null, to be able to cater to codegen features
        /// that are about to generate a local declaration and do not have this information to pass in.
        /// Things (like analyzers) that do have a local declaration already, should pass this in.
        /// </remarks>
        public static bool IsTypeApparentInAssignmentExpression(
            TypeStylePreference stylePreferences,
            ExpressionSyntax initializerExpression,
            SemanticModel semanticModel,
            CancellationToken cancellationToken,
            ITypeSymbol typeInDeclaration = null)
        {
            // default(type)
            if (initializerExpression.IsKind(SyntaxKind.DefaultExpression))
            {
                return true;
            }

            // literals, use var if options allow usage here.
            if (initializerExpression.IsAnyLiteralExpression())
            {
                return stylePreferences.HasFlag(TypeStylePreference.ImplicitTypeForIntrinsicTypes);
            }

            // constructor invocations cases:
            //      = new type();
            if (initializerExpression.IsKind(SyntaxKind.ObjectCreationExpression) &&
                !initializerExpression.IsKind(SyntaxKind.AnonymousObjectCreationExpression))
            {
                return true;
            }

            // explicit conversion cases: 
            //      (type)expr, expr is type, expr as type
            if (initializerExpression.IsKind(SyntaxKind.CastExpression) ||
                initializerExpression.IsKind(SyntaxKind.IsExpression) ||
                initializerExpression.IsKind(SyntaxKind.AsExpression))
            {
                return true;
            }

            // other Conversion cases:
            //      a. conversion with helpers like: int.Parse methods
            //      b. types that implement IConvertible and then invoking .ToType()
            //      c. System.Convert.Totype()
            var memberName = GetRightmostInvocationExpression(initializerExpression).GetRightmostName();
            if (memberName == null)
            {
                return false;
            }

            var methodSymbol = semanticModel.GetSymbolInfo(memberName, cancellationToken).Symbol as IMethodSymbol;
            if (methodSymbol == null)
            {
                return false;
            }

            if (memberName.IsRightSideOfDot())
            {
                var containingTypeName = memberName.GetLeftSideOfDot();
                return IsPossibleCreationOrConversionMethod(methodSymbol, typeInDeclaration, semanticModel, containingTypeName, cancellationToken);
            }

            return false;
        }
示例#11
0
        /// <summary>
        /// Determines whether the specified TypeSyntax is actually 'var'.
        /// </summary>
        public static bool IsTypeInferred(this TypeSyntax typeSyntax, SemanticModel semanticModel)
        {
            if (!typeSyntax.IsVar)
            {
                return false;
            }

            if (semanticModel.GetAliasInfo(typeSyntax) != null)
            {
                return false;
            }

            var type = semanticModel.GetTypeInfo(typeSyntax).Type;
            if (type == null)
            {
                return false;
            }

            if (type.Name == "var")
            {
                return false;
            }

            return true;
        }
示例#12
0
        public static IAliasSymbol GetAliasInfo(
            ISemanticFactsService semanticFacts, SemanticModel model, SyntaxToken token, CancellationToken cancellationToken)
        {
            if (semanticFacts == null)
            {
                return model.GetAliasInfo(token.Parent, cancellationToken);
            }

            var entry = GetCachedEntry(model);
            if (entry == null)
            {
                return model.GetAliasInfo(token.Parent, cancellationToken);
            }

            if (entry.AliasNameSet == null)
            {
                var set = semanticFacts.GetAliasNameSet(model, cancellationToken);
                Interlocked.CompareExchange(ref entry.AliasNameSet, set, null);
            }

            if (entry.AliasNameSet.Contains(token.ValueText))
            {
                return model.GetAliasInfo(token.Parent, cancellationToken);
            }

            return null;
        }
 internal TypeInferrer(
     SemanticModel semanticModel,
     CancellationToken cancellationToken)
 {
     this.semanticModel = semanticModel;
     this.cancellationToken = cancellationToken;
 }
        internal override Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, CancellationToken cancellationToken)
        {
            var actions = ImmutableArray.CreateBuilder<CodeAction>();

            // Fix 1: Add a NonSerialized attribute to the field
            var fieldNode = GetFieldDeclarationNode(nodeToFix);
            if (fieldNode != null)
            {
                var generator = SyntaxGenerator.GetGenerator(document);
                var codeAction = new MyDocumentCodeAction(FxCopFixersResources.AddNonSerializedAttribute,
                                                          async ct => await AddNonSerializedAttribute(document, model, root, fieldNode, generator).ConfigureAwait(false));
                actions.Add(codeAction);

                // Fix 2: If the type of the field is defined in source, then add the serializable attribute to the type.
                var fieldSymbol = model.GetDeclaredSymbol(nodeToFix, cancellationToken) as IFieldSymbol;
                var type = fieldSymbol.Type;
                if (type.Locations.Any(l => l.IsInSource))
                {
                    var typeCodeAction = new MySolutionCodeAction(FxCopFixersResources.AddSerializableAttribute,
                                                                  async ct => await AddSerializableAttributeToType(document, model, generator, type, cancellationToken).ConfigureAwait(false));

                    actions.Add(typeCodeAction);
                }
            }

            return Task.FromResult<IEnumerable<CodeAction>>(actions.ToImmutable());
        }
 private Task<Document> AddNonSerializedAttribute(Document document, SemanticModel model, SyntaxNode root, SyntaxNode fieldNode, SyntaxGenerator generator)
 {
     var attr = generator.Attribute(generator.TypeExpression(WellKnownTypes.NonSerializedAttribute(model.Compilation)));
     var newNode = generator.AddAttributes(fieldNode, attr);
     var newDocument = document.WithSyntaxRoot(root.ReplaceNode(fieldNode, newNode));
     return Task.FromResult(newDocument);
 }
 private bool TypeHasWeakIdentity(ITypeSymbol type, SemanticModel model)
 {
     switch (type.TypeKind)
     {
         case TypeKind.ArrayType:
             var arrayType = type as IArrayTypeSymbol;
             return arrayType != null && arrayType.ElementType.IsPrimitiveType();
         case TypeKind.Class:
         case TypeKind.TypeParameter:
             Compilation compilation = model.Compilation;
             INamedTypeSymbol marshalByRefObjectTypeSymbol = compilation.GetTypeByMetadataName("System.MarshalByRefObject");
             INamedTypeSymbol executionEngineExceptionTypeSymbol = compilation.GetTypeByMetadataName("System.ExecutionEngineException");
             INamedTypeSymbol outOfMemoryExceptionTypeSymbol = compilation.GetTypeByMetadataName("System.OutOfMemoryException");
             INamedTypeSymbol stackOverflowExceptionTypeSymbol = compilation.GetTypeByMetadataName("System.StackOverflowException");
             INamedTypeSymbol memberInfoTypeSymbol = compilation.GetTypeByMetadataName("System.Reflection.MemberInfo");
             INamedTypeSymbol parameterInfoTypeSymbol = compilation.GetTypeByMetadataName("System.Reflection.ParameterInfo");
             INamedTypeSymbol threadTypeSymbol = compilation.GetTypeByMetadataName("System.Threading.Thread");
             return
                 type.SpecialType == SpecialType.System_String ||
                 type.Equals(executionEngineExceptionTypeSymbol) ||
                 type.Equals(outOfMemoryExceptionTypeSymbol) ||
                 type.Equals(stackOverflowExceptionTypeSymbol) ||
                 type.Inherits(marshalByRefObjectTypeSymbol) ||
                 type.Inherits(memberInfoTypeSymbol) ||
                 type.Inherits(parameterInfoTypeSymbol) ||
                 type.Inherits(threadTypeSymbol);
         
         // What about struct types?
         default:
             return false;
     }
 }
示例#17
0
        private bool TryClassifySymbol(
            NameSyntax name,
            SymbolInfo symbolInfo,
            SemanticModel semanticModel,
            CancellationToken cancellationToken,
            out IEnumerable<ClassifiedSpan> result)
        {
            if (symbolInfo.CandidateReason == CandidateReason.Ambiguous)
            {
                return TryClassifyAmbiguousSymbol(name, symbolInfo, semanticModel, cancellationToken, out result);
            }

            // Only classify if we get one good symbol back, or if it bound to a constructor symbol with
            // overload resolution/accessibility errors, or bound to type/constructor and type wasn't creatable.
            var symbol = TryGetSymbol(name, symbolInfo, semanticModel);

            ClassifiedSpan classifiedSpan;
            if (TryClassifySymbol(name, symbol, semanticModel, cancellationToken, out classifiedSpan))
            {
                result = SpecializedCollections.SingletonEnumerable(classifiedSpan);
                return true;
            }

            result = null;
            return false;
        }
 /// <summary>
 /// Returns true if type information could be gleaned by simply looking at the given statement.
 /// This typically means that the type name occurs in right hand side of an assignment.
 /// </summary>
 private bool IsTypeApparentInDeclaration(VariableDeclarationSyntax variableDeclaration, SemanticModel semanticModel, TypeStylePreference stylePreferences, CancellationToken cancellationToken)
 {
     var initializer = variableDeclaration.Variables.Single().Initializer;
     var initializerExpression = GetInitializerExpression(initializer);
     var declaredTypeSymbol = semanticModel.GetTypeInfo(variableDeclaration.Type, cancellationToken).Type;
     return TypeStyleHelper.IsTypeApparentInAssignmentExpression(stylePreferences, initializerExpression, semanticModel,cancellationToken, declaredTypeSymbol);
 }
示例#19
0
        private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out SemanticModel speculativeModel)
        {
            position = CheckAndAdjustPosition(position);

            var methodSymbol = (MethodSymbol)this.MemberSymbol;

            // Strip off ExecutableCodeBinder (see ctor).
            Binder binder = this.RootBinder;

            do
            {
                if (binder is ExecutableCodeBinder)
                {
                    binder = binder.Next;
                    break;
                }

                binder = binder.Next;
            }
            while (binder != null);

            Debug.Assert(binder != null);

            var executablebinder = new ExecutableCodeBinder(body, methodSymbol, binder ?? this.RootBinder);
            var blockBinder = executablebinder.GetBinder(body).WithAdditionalFlags(GetSemanticModelBinderFlags());
            speculativeModel = CreateSpeculative(parentModel, methodSymbol, body, blockBinder, position);
            return true;
        }
 internal SyntaxNode CreateOrdinalMemberAccess(SyntaxGenerator syntaxFactoryService, SemanticModel model)
 {
     var stringComparisonType = WellKnownTypes.StringComparison(model.Compilation);
     return syntaxFactoryService.MemberAccessExpression(
         syntaxFactoryService.TypeExpression(stringComparisonType),
         syntaxFactoryService.IdentifierName(CA1309DiagnosticAnalyzer.OrdinalText));
 }
示例#21
0
        public static void AddAliasSymbols(SemanticModel semanticModel, int namespaceId, IEnumerable<IAliasSymbol> aliasSymbols)
        {
            // given semantic model must be the original semantic model for now
            var treeMap = s_treeAliasMap.GetValue(semanticModel.Compilation, s_createTreeMap);

            // check again to see whether somebody has beaten us
            var key = (tree: semanticModel.SyntaxTree, namespaceId: namespaceId);
            if (treeMap.ContainsKey(key))
            {
                return;
            }

            var builder = ImmutableDictionary.CreateBuilder<INamespaceOrTypeSymbol, IAliasSymbol>();
            foreach (var alias in aliasSymbols)
            {
                if (builder.ContainsKey(alias.Target))
                {
                    continue;
                }

                // only put the first one.
                builder.Add(alias.Target, alias);
            }

            // Use namespace id rather than holding onto namespace node directly, that will keep the tree alive as long as
            // the compilation is alive. In the current design, a node can come and go even if compilation is alive through recoverable tree.
            treeMap.TryAdd(key, builder.ToImmutable());
        }
示例#22
0
 internal static SemanticMap From(SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken)
 {
     var map = new SemanticMap();
     var walker = new Walker(semanticModel, map, cancellationToken);
     walker.Visit(node);
     return map;
 }
        private bool CheckStatement(SemanticModel semanticModel, StatementSyntax statement, CancellationToken cancellationToken)
        {
            if (statement is CheckedStatementSyntax ||
                statement is DoStatementSyntax ||
                statement is EmptyStatementSyntax ||
                statement is ExpressionStatementSyntax ||
                statement is FixedStatementSyntax ||
                statement is ForEachStatementSyntax ||
                statement is ForStatementSyntax ||
                statement is IfStatementSyntax ||
                statement is LocalDeclarationStatementSyntax ||
                statement is LockStatementSyntax ||
                statement is ReturnStatementSyntax ||
                statement is SwitchStatementSyntax ||
                statement is ThrowStatementSyntax ||
                statement is TryStatementSyntax ||
                statement is UnsafeStatementSyntax ||
                statement is UsingStatementSyntax ||
                statement is WhileStatementSyntax)
            {
                return true;
            }

            return false;
        }
        /// <summary>
        /// Checks if any property in the class given as parameter has a getter for the field we are moving.
        /// </summary>
        /// <param name="node">Syntax node of the class the field belongs to.</param>
        /// <param name="semanticModel">Semantic model for the code we are processing.</param>
        /// <returns></returns>
        private PropertyDeclarationSyntax getProperty(ClassDeclarationSyntax node, SemanticModel semanticModel)
        {
            foreach (var p in node.Members.Where(m => m.Kind == SyntaxKind.PropertyDeclaration))
            {
                var property = p as PropertyDeclarationSyntax;

                var accessors = property.AccessorList.Accessors;
                var getter = accessors.FirstOrDefault(ad => ad.Kind == SyntaxKind.GetAccessorDeclaration);

                var statements = getter.BodyOpt.Statements;
                if (statements.Count != 0)
                {
                    var returnStatement = statements.FirstOrDefault() as ReturnStatementSyntax;
                    if (returnStatement != null && returnStatement.ExpressionOpt != null)
                    {
                        var semanticInfo = document.GetSemanticModel().GetSemanticInfo(returnStatement.ExpressionOpt);
                        var fieldSymbol = semanticInfo.Symbol as FieldSymbol;

                        if (fieldSymbol != null && fieldSymbol == semanticModel.GetDeclaredSymbol(field))
                        {
                            return property;
                        }
                    }
                }
            }

            return null;
        }
        public override IEnumerable<SymbolDisplayPart> GetAnonymousTypeParts(
            INamedTypeSymbol anonymousType, SemanticModel semanticModel, int position, ISymbolDisplayService displayService)
        {
            var members = new List<SymbolDisplayPart>();

            members.Add(Keyword(SyntaxFacts.GetText(SyntaxKind.NewKeyword)));
            members.AddRange(Space());
            members.Add(Punctuation(SyntaxFacts.GetText(SyntaxKind.OpenBraceToken)));
            members.AddRange(Space());

            bool first = true;
            foreach (var property in anonymousType.GetValidAnonymousTypeProperties())
            {
                if (!first)
                {
                    members.Add(Punctuation(SyntaxFacts.GetText(SyntaxKind.CommaToken)));
                    members.AddRange(Space());
                }

                first = false;
                members.AddRange(displayService.ToMinimalDisplayParts(semanticModel, position, property.Type).Select(p => p.MassageErrorTypeNames("?")));
                members.AddRange(Space());
                members.Add(new SymbolDisplayPart(SymbolDisplayPartKind.PropertyName, property, property.Name));
            }

            members.AddRange(Space());
            members.Add(Punctuation(SyntaxFacts.GetText(SyntaxKind.CloseBraceToken)));

            return members;
        }
        private static bool IsRequiredCastForReferenceEqualityComparison(ITypeSymbol outerType, CastExpressionSyntax castExpression, SemanticModel semanticModel, out ExpressionSyntax other)
        {
            if (outerType.SpecialType == SpecialType.System_Object)
            {
                var expression = castExpression.WalkUpParentheses();
                var parentNode = expression.Parent;
                if (parentNode.IsKind(SyntaxKind.EqualsExpression) || parentNode.IsKind(SyntaxKind.NotEqualsExpression))
                {
                    // Reference comparison.
                    var binaryExpression = (BinaryExpressionSyntax)parentNode;
                    other = binaryExpression.Left == expression ?
                        binaryExpression.Right :
                        binaryExpression.Left;

                    // Explicit cast not required if we are comparing with type parameter with a class constraint.
                    var otherType = semanticModel.GetTypeInfo(other).Type;
                    if (otherType != null && otherType.TypeKind != TypeKind.TypeParameter)
                    {
                        return !other.WalkDownParentheses().IsKind(SyntaxKind.CastExpression);
                    }
                }
            }

            other = null;
            return false;
        }
        internal override Task<Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, string diagnosticId, CancellationToken cancellationToken)
        {
            // if nothing can be fixed, return the unchanged node
            var newRoot = root;
            var kind = nodeToFix.CSharpKind();
            var syntaxFactoryService = document.GetLanguageService<SyntaxGenerator>();
            switch (kind)
            {
                case SyntaxKind.Argument:
                    // StringComparison.CurrentCulture => StringComparison.Ordinal
                    // StringComparison.CurrentCultureIgnoreCase => StringComparison.OrdinalIgnoreCase
                    var argument = (ArgumentSyntax)nodeToFix;
                    var memberAccess = argument.Expression as MemberAccessExpressionSyntax;
                    if (memberAccess != null)
                    {
                        // preserve the "IgnoreCase" suffix if present
                        bool isIgnoreCase = memberAccess.Name.GetText().ToString().EndsWith(CA1309DiagnosticAnalyzer.IgnoreCaseText);
                        var newOrdinalText = isIgnoreCase ? CA1309DiagnosticAnalyzer.OrdinalIgnoreCaseText : CA1309DiagnosticAnalyzer.OrdinalText;
                        var newIdentifier = syntaxFactoryService.IdentifierName(newOrdinalText);
                        var newMemberAccess = memberAccess.WithName((SimpleNameSyntax)newIdentifier).WithAdditionalAnnotations(Formatter.Annotation);
                        newRoot = root.ReplaceNode(memberAccess, newMemberAccess);
                    }

                    break;
                case SyntaxKind.IdentifierName:
                    // string.Equals(a, b) => string.Equals(a, b, StringComparison.Ordinal)
                    // string.Compare(a, b) => string.Compare(a, b, StringComparison.Ordinal)
                    var identifier = (IdentifierNameSyntax)nodeToFix;
                    var invokeParent = identifier.GetAncestor<InvocationExpressionSyntax>();
                    if (invokeParent != null)
                    {
                        var methodSymbol = model.GetSymbolInfo(identifier).Symbol as IMethodSymbol;
                        if (methodSymbol != null && CanAddStringComparison(methodSymbol))
                        {
                            // append a new StringComparison.Ordinal argument
                            var newArg = syntaxFactoryService.Argument(CreateOrdinalMemberAccess(syntaxFactoryService, model))
                                .WithAdditionalAnnotations(Formatter.Annotation);
                            var newInvoke = invokeParent.AddArgumentListArguments((ArgumentSyntax)newArg).WithAdditionalAnnotations(Formatter.Annotation);
                            newRoot = root.ReplaceNode(invokeParent, newInvoke);
                        }
                    }

                    break;
                case SyntaxKind.EqualsExpression:
                case SyntaxKind.NotEqualsExpression:
                    // "a == b" => "string.Equals(a, b, StringComparison.Ordinal)"
                    // "a != b" => "!string.Equals(a, b, StringComparison.Ordinal)"
                    var binaryExpression = (BinaryExpressionSyntax)nodeToFix;
                    var invocation = CreateEqualsExpression(syntaxFactoryService, model, binaryExpression.Left, binaryExpression.Right, kind == SyntaxKind.EqualsExpression).WithAdditionalAnnotations(Formatter.Annotation);
                    newRoot = root.ReplaceNode(nodeToFix, invocation);
                    break;
            }

            if (newRoot == root)
            {
                return Task.FromResult(document);
            }

            return Task.FromResult(document.WithSyntaxRoot(newRoot));
        }
 protected static bool IsAcceptableOverload(IMethodSymbol methodSymbol, SemanticModel model)
 {
     var stringComparisonType = WellKnownTypes.StringComparison(model.Compilation);
     return methodSymbol.IsStatic
         ? IsAcceptableStaticOverload(methodSymbol, stringComparisonType)
         : IsAcceptableInstanceOverload(methodSymbol, stringComparisonType);
 }
        private async Task<SyntaxNode> AddNamespaceImportsAsync(
            Document document,
            SemanticModel model,
            OptionSet options,
            IEnumerable<INamespaceSymbol> namespaces,
            CancellationToken cancellationToken)
        {
            var existingNamespaces = new HashSet<INamespaceSymbol>();
            await this.GetExistingImportedNamespacesAsync(document, model, existingNamespaces, cancellationToken).ConfigureAwait(false);

            var namespacesToAdd = new HashSet<INamespaceSymbol>(namespaces);
            namespacesToAdd.RemoveAll(existingNamespaces);

            var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
            if (namespacesToAdd.Count == 0)
            {
                return root;
            }

            var gen = SyntaxGenerator.GetGenerator(document);

            var newRoot = root;
            foreach (var import in namespacesToAdd.Select(ns => gen.NamespaceImportDeclaration(ns.ToDisplayString()).WithAdditionalAnnotations(Simplifier.Annotation)))
            {
                newRoot = this.InsertNamespaceImport(newRoot, gen, import, options);
            }

            return newRoot;
        }
            public PostProcessor(SemanticModel semanticModel, int contextPosition)
            {
                Contract.ThrowIfNull(semanticModel);

                _semanticModel = semanticModel;
                _contextPosition = contextPosition;
            }
        private static IEnumerable<ITypeSymbol> ExtractTypeSymbolsFromSyntaxNode(SyntaxNode node, SemanticModel model)
        {
            var parameter = node as ParameterSyntax;
            if (parameter?.Type != null)
            {
                yield return model.GetSymbolInfo(parameter.Type).Symbol as ITypeSymbol;
            }

            if (node is VariableDeclarationSyntax variableDeclaration)
            {
                yield return model.GetSymbolInfo(variableDeclaration.Type).Symbol as ITypeSymbol;
            }

            if (node is ObjectCreationExpressionSyntax objectCreation)
            {
                var objectCreationTypeInfo = model.GetTypeInfo(objectCreation);
                yield return objectCreationTypeInfo.Type;
                yield return objectCreationTypeInfo.ConvertedType;
            }

            if (node is IdentifierNameSyntax identifierName)
            {
                yield return model.GetSymbolInfo(identifierName).Symbol as ITypeSymbol;
            }
        }
        private static async Task <Document> RemoveArgumentsAndAddNecessaryNamesAsync(Document document, ArgumentListSyntax argumentList,
                                                                                      List <SyntaxNodeSymbolSemanticModelTuple <ArgumentSyntax, IParameterSymbol> > argumentMappings, List <ArgumentSyntax> argumentsToRemove,
                                                                                      SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var newArgumentList   = SyntaxFactory.ArgumentList();
            var alreadyRemovedOne = false;

            foreach (var argumentMapping in argumentMappings
                     .Where(argumentMapping => !argumentMapping.Symbol.IsParams))
            {
                var argument = argumentMapping.SyntaxNode;
                if (argumentsToRemove.Contains(argument))
                {
                    alreadyRemovedOne = true;
                    continue;
                }

                newArgumentList = AddArgument(newArgumentList, argumentMapping.Symbol.Name, argument, alreadyRemovedOne);
            }

            var paramsArguments = argumentMappings
                                  .Where(mapping => mapping.Symbol.IsParams)
                                  .ToList();

            if (paramsArguments.Any())
            {
                newArgumentList = AddParamsArguments(semanticModel, paramsArguments, newArgumentList);
            }

            var newRoot = root.ReplaceNode(argumentList, newArgumentList);

            return(document.WithSyntaxRoot(newRoot));
        }
 protected abstract void AnalyzeNode(SymbolAnalysisContext symbolContext, TSyntaxNodeOfInterest syntaxNode, SemanticModel semanticModel);
示例#34
0
        private static async Task <Document> Fix(CodeFixContext context, SyntaxNode root, SyntaxGenerator generator, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            SyntaxNode node       = root.FindNode(context.Span);
            Diagnostic diagnostic = context.Diagnostics.First();

            switch (diagnostic.Properties[OperatorOverloadsHaveNamedAlternatesAnalyzer.DiagnosticKindText])
            {
            case OperatorOverloadsHaveNamedAlternatesAnalyzer.AddAlternateText:
                SyntaxNode       methodDeclaration      = generator.GetDeclaration(node, DeclarationKind.Operator) ?? generator.GetDeclaration(node, DeclarationKind.ConversionOperator);
                var              operatorOverloadSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(methodDeclaration, cancellationToken);
                INamedTypeSymbol typeSymbol             = operatorOverloadSymbol.ContainingType;

                // For C# the following `typeDeclarationSyntax` and `typeDeclaration` nodes are identical, but for VB they're different so in
                // an effort to keep this as language-agnostic as possible, the heavy-handed approach is used.
                SyntaxNode typeDeclarationSyntax = typeSymbol.DeclaringSyntaxReferences.First().GetSyntax(cancellationToken);
                SyntaxNode typeDeclaration       = generator.GetDeclaration(typeDeclarationSyntax,
                                                                            typeSymbol.TypeKind == TypeKind.Struct ? DeclarationKind.Struct : DeclarationKind.Class);

                SyntaxNode addedMember;
                IEnumerable <SyntaxNode> bodyStatements = generator.DefaultMethodBody(semanticModel.Compilation);
                if (OperatorOverloadsHaveNamedAlternatesAnalyzer.IsPropertyExpected(operatorOverloadSymbol.Name))
                {
                    // add a property
                    addedMember = generator.PropertyDeclaration(
                        name: OperatorOverloadsHaveNamedAlternatesAnalyzer.IsTrueText,
                        type: generator.TypeExpression(SpecialType.System_Boolean),
                        accessibility: Accessibility.Public,
                        modifiers: DeclarationModifiers.ReadOnly,
                        getAccessorStatements: bodyStatements);
                }
                else
                {
                    // add a method
                    ExpectedMethodSignature expectedSignature = GetExpectedMethodSignature(operatorOverloadSymbol, semanticModel.Compilation);

                    if (expectedSignature.Name == "CompareTo" && operatorOverloadSymbol.ContainingType.TypeKind == TypeKind.Class)
                    {
                        var nullCheck = generator.IfStatement(
                            generator.InvocationExpression(
                                generator.IdentifierName("ReferenceEquals"),
                                generator.IdentifierName(expectedSignature.Parameters.First().name),
                                generator.NullLiteralExpression()),
                            new[]
                        {
                            generator.ReturnStatement(generator.LiteralExpression(1))
                        });

                        bodyStatements = new[] { nullCheck }.Concat(bodyStatements);
                    }

                    addedMember = generator.MethodDeclaration(
                        name: expectedSignature.Name,
                        parameters: expectedSignature.Parameters.Select(p => generator.ParameterDeclaration(p.name, generator.TypeExpression(p.typeSymbol))),
                        returnType: generator.TypeExpression(expectedSignature.ReturnType),
                        accessibility: Accessibility.Public,
                        modifiers: expectedSignature.IsStatic ? DeclarationModifiers.Static : DeclarationModifiers.None,
                        statements: bodyStatements);
                }

                SyntaxNode newTypeDeclaration = generator.AddMembers(typeDeclaration, addedMember);
                return(context.Document.WithSyntaxRoot(root.ReplaceNode(typeDeclaration, newTypeDeclaration)));

            case OperatorOverloadsHaveNamedAlternatesAnalyzer.FixVisibilityText:
                SyntaxNode   badVisibilityNode   = generator.GetDeclaration(node, DeclarationKind.Method) ?? generator.GetDeclaration(node, DeclarationKind.Property);
                ISymbol      badVisibilitySymbol = semanticModel.GetDeclaredSymbol(badVisibilityNode, cancellationToken);
                SymbolEditor symbolEditor        = SymbolEditor.Create(context.Document);
                ISymbol      newSymbol           = await symbolEditor.EditOneDeclarationAsync(badVisibilitySymbol,
                                                                                              (documentEditor, syntaxNode) => documentEditor.SetAccessibility(badVisibilityNode, Accessibility.Public), cancellationToken).ConfigureAwait(false);

                Document   newDocument = symbolEditor.GetChangedDocuments().Single();
                SyntaxNode newRoot     = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                return(context.Document.WithSyntaxRoot(newRoot));

            default:
                return(context.Document);
            }
        }
 internal abstract CSharpSyntaxRewriter CreateSyntaxRewriter(Compilation compilation, SemanticModel semanticModel);
示例#36
0
        private static ITypeParameterSymbol GetGenericParameterSymbol(ISyntaxFactsService syntaxFacts, SemanticModel semanticModel, SyntaxNode node1, SyntaxNode node2, CancellationToken cancellationToken)
        {
            var valueNode          = syntaxFacts.IsNullLiteralExpression(syntaxFacts.GetExpressionOfArgument(node1)) ? node2 : node1;
            var argumentExpression = syntaxFacts.GetExpressionOfArgument(valueNode);

            if (argumentExpression != null)
            {
                var parameterType = semanticModel.GetTypeInfo(argumentExpression, cancellationToken).Type;
                return(parameterType as ITypeParameterSymbol);
            }

            return(default);
示例#37
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DefaultExpression"/> class.
 /// </summary>
 /// <param name="syntaxNode"></param>
 /// <param name="semanticModel"></param>
 public DefaultExpression(CSharpSyntaxNode syntaxNode, SemanticModel semanticModel)
     : base(syntaxNode, semanticModel)
 {
 }
 private static IEnumerable<ITypeSymbol> CollectCoupledClasses(FieldDeclarationSyntax field,
     SemanticModel model)
 {
     return field.Declaration.Variables
         .SelectMany(variable => ExtractTypesFromVariableDeclarator(variable, model));
 }
 internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out SemanticModel speculativeModel)
 {
     throw ExceptionUtilities.Unreachable;
 }
 private static IEnumerable<ITypeSymbol> CollectCoupledClasses(BaseMethodDeclarationSyntax method,
     SemanticModel model)
 {
     return method.DescendantNodes()
         .SelectMany(node => ExtractTypeSymbolsFromSyntaxNode(node, model));
 }
 internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel)
 {
     throw ExceptionUtilities.Unreachable;
 }
 internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out SemanticModel speculativeModel)
 {
     throw ExceptionUtilities.Unreachable;
 }
        private static MethodArgumentDescriptor[] GetArgumentDescriptors(List <ParameterSyntax> argumentList, SemanticModel semanticModel, MockFramework mockFramework)
        {
            MethodArgumentDescriptor[] argumentDescriptors = new MethodArgumentDescriptor[argumentList.Count()];

            for (int i = 0; i < argumentDescriptors.Count(); i++)
            {
                string argumentName = argumentList[i].Identifier.Text;

                ParameterModifier modifier = GetArgumentModifier(argumentList[i]);

                var namedTypeSymbol = InjectableType.TryCreateInjectableTypeFromParameterNode(argumentList[i], semanticModel, mockFramework);

                if (namedTypeSymbol != null)
                {
                    argumentDescriptors[i] = new MethodArgumentDescriptor(namedTypeSymbol, argumentName, modifier);
                    continue;
                }

                var argumentType = argumentList[i].Type;

                string typeName = argumentType.ToString();

                argumentDescriptors[i] = new MethodArgumentDescriptor(new TypeDescriptor(typeName, null), argumentName, modifier);
            }

            return(argumentDescriptors);
        }
 internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel speculativeModel)
 {
     throw ExceptionUtilities.Unreachable;
 }
示例#45
0
 public RDomReturnStatement(SyntaxNode rawItem, IDom parent, SemanticModel model)
     : base(rawItem, parent, model)
 {
 }
 internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel)
 {
     throw ExceptionUtilities.Unreachable;
 }
示例#47
0
 public InvocationVisitor(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ProgramState programState)
 {
     this.invocation    = invocation;
     this.semanticModel = semanticModel;
     this.programState  = programState;
 }
        private async Task <TestGenerationContext> CollectTestGenerationContextAsync(
            ProjectItemSummary selectedFile,
            string targetProjectNamespace,
            TestFramework testFramework,
            MockFramework mockFramework)
        {
            Microsoft.CodeAnalysis.Solution solution = CreateUnitTestBoilerplateCommandPackage.VisualStudioWorkspace.CurrentSolution;
            DocumentId documentId = solution.GetDocumentIdsWithFilePath(selectedFile.FilePath).FirstOrDefault();

            if (documentId == null)
            {
                throw new InvalidOperationException("Could not find document in solution with file path " + selectedFile.FilePath);
            }

            var document = solution.GetDocument(documentId);

            SyntaxNode root = await document.GetSyntaxRootAsync();

            SemanticModel semanticModel = await document.GetSemanticModelAsync();

            SyntaxNode firstClassDeclaration = root.DescendantNodes().FirstOrDefault(node => node.Kind() == SyntaxKind.ClassDeclaration);

            if (firstClassDeclaration == null)
            {
                throw new InvalidOperationException("Could not find class declaration.");
            }

            if (firstClassDeclaration.ChildTokens().Any(node => node.Kind() == SyntaxKind.AbstractKeyword))
            {
                throw new InvalidOperationException("Cannot unit test an abstract class.");
            }

            SyntaxToken classIdentifierToken = firstClassDeclaration.ChildTokens().FirstOrDefault(n => n.Kind() == SyntaxKind.IdentifierToken);

            if (classIdentifierToken == default(SyntaxToken))
            {
                throw new InvalidOperationException("Could not find class identifier.");
            }

            NamespaceDeclarationSyntax namespaceDeclarationSyntax = null;

            if (!TypeUtilities.TryGetParentSyntax(firstClassDeclaration, out namespaceDeclarationSyntax))
            {
                throw new InvalidOperationException("Could not find class namespace.");
            }

            // Find property injection types
            var injectableProperties = new List <InjectableProperty>();

            string           classFullName = namespaceDeclarationSyntax.Name + "." + classIdentifierToken;
            INamedTypeSymbol classType     = semanticModel.Compilation.GetTypeByMetadataName(classFullName);

            foreach (ISymbol member in classType.GetBaseTypesAndThis().SelectMany(n => n.GetMembers()))
            {
                if (member.Kind == SymbolKind.Property)
                {
                    IPropertySymbol property = (IPropertySymbol)member;

                    foreach (AttributeData attribute in property.GetAttributes())
                    {
                        if (PropertyInjectionAttributeNames.Contains(attribute.AttributeClass.ToString()))
                        {
                            var injectableProperty = InjectableProperty.TryCreateInjectableProperty(property.Name, property.Type.ToString(), mockFramework);
                            if (injectableProperty != null)
                            {
                                injectableProperties.Add(injectableProperty);
                            }
                        }
                    }
                }
            }

            string className = classIdentifierToken.ToString();

            // Find constructor injection types
            List <InjectableType> constructorInjectionTypes = new List <InjectableType>();

            SyntaxNode constructorDeclaration = firstClassDeclaration.ChildNodes().FirstOrDefault(n => n.Kind() == SyntaxKind.ConstructorDeclaration);

            if (constructorDeclaration != null)
            {
                constructorInjectionTypes.AddRange(
                    GetParameterListNodes(constructorDeclaration)
                    .Select(node => InjectableType.TryCreateInjectableTypeFromParameterNode(node, semanticModel, mockFramework)));
            }

            // Find public method declarations
            IList <MethodDescriptor> methodDeclarations = new List <MethodDescriptor>();

            foreach (MethodDeclarationSyntax methodDeclaration in
                     firstClassDeclaration.ChildNodes().Where(
                         n => n.Kind() == SyntaxKind.MethodDeclaration &&
                         ((MethodDeclarationSyntax)n).Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword))))
            {
                var parameterList = GetParameterListNodes(methodDeclaration).ToList();

                var parameterTypes = GetArgumentDescriptors(parameterList, semanticModel, mockFramework);

                var isAsync =
                    methodDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.AsyncKeyword)) ||
                    DoesReturnTask(methodDeclaration);

                var hasReturnType = !DoesReturnNonGenericTask(methodDeclaration) && !DoesReturnVoid(methodDeclaration);

                methodDeclarations.Add(new MethodDescriptor(methodDeclaration.Identifier.Text, parameterTypes, isAsync, hasReturnType));
            }

            string unitTestNamespace;

            string relativePath = this.GetRelativePath(selectedFile);

            if (string.IsNullOrEmpty(relativePath))
            {
                unitTestNamespace = targetProjectNamespace;
            }
            else
            {
                List <string> defaultNamespaceParts  = targetProjectNamespace.Split('.').ToList();
                List <string> unitTestNamespaceParts = new List <string>(defaultNamespaceParts);
                unitTestNamespaceParts.AddRange(relativePath.Split('\\'));

                unitTestNamespace = string.Join(".", unitTestNamespaceParts);
            }

            List <InjectableType> injectedTypes = new List <InjectableType>(injectableProperties);

            injectedTypes.AddRange(constructorInjectionTypes.Where(t => t != null));

            GenerateMockNames(injectedTypes);

            return(new TestGenerationContext(
                       mockFramework,
                       testFramework,
                       unitTestNamespace,
                       className,
                       namespaceDeclarationSyntax.Name.ToString(),
                       injectableProperties,
                       constructorInjectionTypes,
                       injectedTypes,
                       methodDeclarations));
        }
示例#49
0
        private static SyntaxNode GenerateDescriptionArgument(SyntaxGenerator generator, SemanticModel semanticModel)
        {
            SyntaxNode attributeArgument;

            if (semanticModel.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisHostMefMefConstruction, out var mefConstructionType) &&
                mefConstructionType.GetMembers("ImportingConstructorMessage").OfType <IFieldSymbol>().Any())
            {
                attributeArgument = generator.MemberAccessExpression(
                    generator.TypeExpressionForStaticMemberAccess(mefConstructionType),
                    generator.IdentifierName("ImportingConstructorMessage"));
            }
            else
            {
                attributeArgument = generator.LiteralExpression("This exported object must be obtained through the MEF export provider.");
            }

            return(generator.AttributeArgument(attributeArgument));
        }
示例#50
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out ExpressionSyntax expression, predicate: f => f.IsKind(SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression)))
            {
                return;
            }

            if (IsPartOfLeftSideOfAssignment())
            {
                return;
            }

            if (expression
                .WalkUp(f => f.IsKind(SyntaxKind.InvocationExpression, SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression, SyntaxKind.ParenthesizedExpression))
                .IsParentKind(SyntaxKind.AwaitExpression))
            {
                return;
            }

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            if (expression.IsInExpressionTree(semanticModel, context.CancellationToken))
            {
                return;
            }

            SyntaxKind kind = expression.Kind();

            if (kind == SyntaxKind.SimpleMemberAccessExpression)
            {
                expression = ((MemberAccessExpressionSyntax)expression).Expression;
            }
            else if (kind == SyntaxKind.ElementAccessExpression)
            {
                expression = ((ElementAccessExpressionSyntax)expression).Expression;
            }

            CodeAction codeAction = CodeAction.Create(
                "Use conditional access",
                cancellationToken => RefactorAsync(context.Document, expression, cancellationToken),
                GetEquivalenceKey(DiagnosticIdentifiers.AvoidNullReferenceException));

            context.RegisterCodeFix(codeAction, context.Diagnostics);

            bool IsPartOfLeftSideOfAssignment()
            {
                for (SyntaxNode node = expression; node != null; node = node.Parent)
                {
                    var assignmentExpression = node.Parent as AssignmentExpressionSyntax;

                    if (assignmentExpression?.Left == node)
                    {
                        return(true);
                    }
                }

                return(false);
            }
        }
            private ImmutableArray <IFieldSymbol> GetReferencedDescriptorFields(SyntaxNode syntax, SemanticModel semanticModel)
            {
                ImmutableArray <IFieldSymbol> .Builder builder = ImmutableArray.CreateBuilder <IFieldSymbol>();
                foreach (TIdentifierNameSyntax identifier in syntax.DescendantNodes().OfType <TIdentifierNameSyntax>())
                {
                    ISymbol symbol = semanticModel.GetSymbolInfo(identifier).Symbol;
                    if (symbol != null && symbol.Kind == SymbolKind.Field)
                    {
                        var field = (IFieldSymbol)symbol;
                        if (field.Type is INamedTypeSymbol fieldType && fieldType.GetBaseTypesAndThis().Contains(_diagnosticDescriptorType))
                        {
                            builder.Add((IFieldSymbol)symbol);
                        }
                    }
                }

                return(builder.ToImmutable());
            }
示例#52
0
 protected abstract void AddAllParameterNameHintLocations(
     SemanticModel semanticModel,
     ISyntaxFactsService syntaxFacts,
     SyntaxNode node,
     ArrayBuilder <(int position, string?identifierArgument, IParameterSymbol?parameter, HintKind kind)> buffer,
示例#53
0
 public CppImplWalker(CSharpCompilation compilation, SemanticModel model, ConversionSettings settings) : base(compilation, model, settings)
 {
 }
            protected override void AnalyzeNode(SymbolAnalysisContext symbolContext, TInvocationExpressionSyntax invocation, SemanticModel semanticModel)
            {
                ISymbol symbol = semanticModel.GetSymbolInfo(invocation, symbolContext.CancellationToken).Symbol;

                if (symbol == null ||
                    symbol.Kind != SymbolKind.Method ||
                    !symbol.Name.Equals(ReportDiagnosticName, StringComparison.OrdinalIgnoreCase) ||
                    !_contextTypes.Contains(symbol.ContainingType))
                {
                    return;
                }

                IEnumerable <SyntaxNode> arguments = GetArgumentExpressions(invocation);

                if (arguments.HasExactly(1))
                {
                    SyntaxNode  argument = arguments.First();
                    ITypeSymbol type     = semanticModel.GetTypeInfo(argument, symbolContext.CancellationToken).ConvertedType;
                    if (type != null && type.Equals(_diagnosticType))
                    {
                        ISymbol argSymbol = semanticModel.GetSymbolInfo(argument, symbolContext.CancellationToken).Symbol;
                        if (argSymbol != null)
                        {
                            SyntaxNode diagnosticInitializerOpt = null;

                            if (argSymbol is ILocalSymbol local)
                            {
                                SyntaxReference syntaxRef = local.DeclaringSyntaxReferences.FirstOrDefault();
                                if (syntaxRef != null)
                                {
                                    diagnosticInitializerOpt = syntaxRef.GetSyntax(symbolContext.CancellationToken).FirstAncestorOrSelf <TVariableDeclaratorSyntax>();
                                }
                            }
                            else
                            {
                                if (argSymbol is IMethodSymbol method &&
                                    method.ContainingType.Equals(_diagnosticType) &&
                                    method.Name.Equals(nameof(Diagnostic.Create), StringComparison.OrdinalIgnoreCase))
                                {
                                    diagnosticInitializerOpt = argument;
                                }
                            }

                            if (diagnosticInitializerOpt != null)
                            {
                                ImmutableArray <IFieldSymbol> descriptorFields = GetReferencedDescriptorFields(diagnosticInitializerOpt, semanticModel);
                                if (descriptorFields.Length == 1 &&
                                    !_supportedDescriptorFieldsMap[(INamedTypeSymbol)symbolContext.Symbol].Contains(descriptorFields[0]))
                                {
                                    Diagnostic diagnostic = Diagnostic.Create(InvalidReportDiagnosticRule, invocation.GetLocation(), descriptorFields[0].Name);
                                    symbolContext.ReportDiagnostic(diagnostic);
                                }
                            }
                        }
                    }
                }
            }
        private static void Analyze(SyntaxNodeAnalysisContext context, SyntaxNode node, BlockSyntax body)
        {
            if (body == null)
            {
                return;
            }

            if (body.ContainsDiagnostics)
            {
                return;
            }

            SyntaxList <StatementSyntax> statements = body.Statements;

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

            if (!(statements[0] is IfStatementSyntax ifStatement))
            {
                return;
            }

            if (!(statements[1] is ReturnStatementSyntax returnStatement))
            {
                return;
            }

            ExpressionSyntax returnExpression = returnStatement.Expression;

            if (returnExpression?.IsKind(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression) != true)
            {
                return;
            }

            if (ifStatement.SpanOrTrailingTriviaContainsDirectives())
            {
                return;
            }

            if (returnStatement.SpanOrLeadingTriviaContainsDirectives())
            {
                return;
            }

            SimpleIfStatementInfo simpleIf = SyntaxInfo.SimpleIfStatementInfo(ifStatement);

            if (!simpleIf.Success)
            {
                return;
            }

            StatementSyntax statement = simpleIf.IfStatement.SingleNonBlockStatementOrDefault();

            if (statement == null)
            {
                return;
            }

            SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(statement);

            if (!assignmentInfo.Success)
            {
                return;
            }

            if (!assignmentInfo.Left.IsKind(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression))
            {
                return;
            }

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

            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(simpleIf.Condition, semanticModel: semanticModel, allowedStyles: NullCheckStyles.CheckingNull, cancellationToken: cancellationToken);

            if (!nullCheck.Success)
            {
                return;
            }

            ExpressionSyntax expression = nullCheck.Expression;

            if (!expression.IsKind(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression))
            {
                return;
            }

            if (!(semanticModel.GetSymbol(expression, cancellationToken) is IFieldSymbol fieldSymbol))
            {
                return;
            }

            if (!ExpressionEquals(expression, assignmentInfo.Left))
            {
                return;
            }

            if (fieldSymbol.Type.IsNullableType() &&
                returnExpression.Kind() == SyntaxKind.SimpleMemberAccessExpression)
            {
                var memberAccessExpression = (MemberAccessExpressionSyntax)returnExpression;

                if (memberAccessExpression.Name is IdentifierNameSyntax identifierName &&
                    string.Equals(identifierName.Identifier.ValueText, "Value", StringComparison.Ordinal))
                {
                    returnExpression = memberAccessExpression.Expression;
                }
            }

            if (!ExpressionEquals(expression, returnExpression))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context,
                                               DiagnosticDescriptors.SimplifyLazyInitialization,
                                               Location.Create(node.SyntaxTree, TextSpan.FromBounds(ifStatement.SpanStart, returnStatement.Span.End)));
        }
示例#56
0
        public static async Task <ISymbol?> FindApplicableAlias(this ITypeSymbol type, int position, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            try
            {
                if (semanticModel.IsSpeculativeSemanticModel)
                {
                    position      = semanticModel.OriginalPositionForSpeculation;
                    semanticModel = semanticModel.ParentModel;
                }

                var root = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

                var applicableUsings = GetApplicableUsings(position, (CompilationUnitSyntax)root);
                foreach (var applicableUsing in applicableUsings)
                {
                    var alias = semanticModel.GetOriginalSemanticModel().GetDeclaredSymbol(applicableUsing, cancellationToken);
                    if (alias != null && Equals(alias.Target, type))
                    {
                        return(alias);
                    }
                }

                return(null);
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
示例#57
0
 private static bool HasFloatingType(ExpressionSyntax right, ExpressionSyntax left, SemanticModel semanticModel)
 {
     return(IsExpressionFloatingType(right, semanticModel) ||
            IsExpressionFloatingType(left, semanticModel));
 }
示例#58
0
        private static void CheckDelegateCreation(SyntaxNode node, TypeInfo typeInfo, SemanticModel semanticModel, bool isAssignmentToReadonly, Action <Diagnostic> reportDiagnostic, Location location, string filePath, CancellationToken cancellationToken)
        {
            // special case: method groups
            if (typeInfo.ConvertedType?.TypeKind == TypeKind.Delegate)
            {
                // new Action<Foo>(MethodGroup); should skip this one
                var insideObjectCreation = node?.Parent?.Parent?.Parent?.Kind() == SyntaxKind.ObjectCreationExpression;
                if (node is ParenthesizedLambdaExpressionSyntax || node is SimpleLambdaExpressionSyntax ||
                    node is AnonymousMethodExpressionSyntax || node is ObjectCreationExpressionSyntax ||
                    insideObjectCreation)
                {
                    // skip this, because it's intended.
                }
                else
                {
                    if (node.IsKind(SyntaxKind.IdentifierName))
                    {
                        if (semanticModel.GetSymbolInfo(node, cancellationToken).Symbol is IMethodSymbol)
                        {
                            reportDiagnostic(Diagnostic.Create(MethodGroupAllocationRule, location, EmptyMessageArgs));
                            HeapAllocationAnalyzerEventSource.Logger.MethodGroupAllocation(filePath);
                        }
                    }
                    else if (node.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                    {
                        var memberAccess = node as MemberAccessExpressionSyntax;
                        if (semanticModel.GetSymbolInfo(memberAccess.Name, cancellationToken).Symbol is IMethodSymbol)
                        {
                            if (isAssignmentToReadonly)
                            {
                                reportDiagnostic(Diagnostic.Create(ReadonlyMethodGroupAllocationRule, location, EmptyMessageArgs));
                                HeapAllocationAnalyzerEventSource.Logger.ReadonlyMethodGroupAllocation(filePath);
                            }
                            else
                            {
                                reportDiagnostic(Diagnostic.Create(MethodGroupAllocationRule, location, EmptyMessageArgs));
                                HeapAllocationAnalyzerEventSource.Logger.MethodGroupAllocation(filePath);
                            }
                        }
                    }
                    else if (node is ArrowExpressionClauseSyntax)
                    {
                        var arrowClause = node as ArrowExpressionClauseSyntax;
                        if (semanticModel.GetSymbolInfo(arrowClause.Expression, cancellationToken).Symbol is IMethodSymbol)
                        {
                            reportDiagnostic(Diagnostic.Create(MethodGroupAllocationRule, location, EmptyMessageArgs));
                            HeapAllocationAnalyzerEventSource.Logger.MethodGroupAllocation(filePath);
                        }
                    }
                }

                var symbolInfo = semanticModel.GetSymbolInfo(node, cancellationToken).Symbol;
                if (symbolInfo?.ContainingType?.IsValueType == true && !insideObjectCreation)
                {
                    reportDiagnostic(Diagnostic.Create(DelegateOnStructInstanceRule, location, EmptyMessageArgs));
                }
            }
        }
示例#59
0
 public static AttributeSyntax FindAttribute(this BaseTypeDeclarationSyntax typeDeclaration, SemanticModel model, string typeName)
 {
     return(typeDeclaration.AttributeLists
            .SelectMany(x => x.Attributes)
            .Where(x => model.GetTypeInfo(x).Type?.ToDisplayString() == typeName)
            .FirstOrDefault());
 }
示例#60
0
 private static bool IsExpressionFloatingType(ExpressionSyntax expression, SemanticModel semanticModel)
 {
     return(semanticModel.GetTypeInfo(expression).Type.IsAny(KnownType.FloatingPointNumbers));
 }