private ReferenceRewriter(
     SemanticModel semanticModel,
     VariableDeclaratorSyntax variableDeclarator,
     ExpressionSyntax expressionToInline,
     CancellationToken cancellationToken)
 {
     _semanticModel = semanticModel;
     _localSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(variableDeclarator, cancellationToken);
     _variableDeclarator = variableDeclarator;
     _expressionToInline = expressionToInline;
     _cancellationToken = cancellationToken;
 }
 private static SyntaxNode CreateRootAddingDisposeToEndOfMethod(SyntaxNode root, ExpressionStatementSyntax statement, ILocalSymbol identitySymbol)
 {
     var method = statement.FirstAncestorOrSelf<MethodDeclarationSyntax>();
     var newDispose = ImplementsDisposableExplicitly(identitySymbol.Type)
         ? SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression(
             SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
             SyntaxFactory.ParenthesizedExpression(SyntaxFactory.CastExpression(SyntaxFactory.ParseName("System.IDisposable").WithAdditionalAnnotations(Simplifier.Annotation), SyntaxFactory.IdentifierName(identitySymbol.Name))),
             SyntaxFactory.IdentifierName("Dispose"))))
         : SyntaxFactory.ParseStatement($"{identitySymbol.Name}.Dispose();");
     newDispose = newDispose.WithAdditionalAnnotations(Formatter.Annotation);
     var last = method.Body.Statements.Last();
     var newRoot = root.InsertNodesAfter(method.Body.Statements.Last(), new[] { newDispose });
     return newRoot;
 }
 private static bool IsDisposedOrAssigned(SemanticModel semanticModel, SyntaxNode node, ILocalSymbol identitySymbol)
 {
     var method = node.FirstAncestorOrSelf<MethodDeclarationSyntax>();
     if (method == null) return false;
     if (IsReturned(method, semanticModel, identitySymbol)) return true;
     foreach (var statement in method.Body.DescendantNodes().OfType<StatementSyntax>())
     {
         if (statement.SpanStart > node.SpanStart
         && (IsCorrectDispose(statement as ExpressionStatementSyntax, semanticModel, identitySymbol)
         || IsAssignedToField(statement as ExpressionStatementSyntax, semanticModel, identitySymbol)))
             return true;
     }
     return false;
 }
예제 #4
0
 /// <summary>
 /// Creates a new LocalDefinition.
 /// </summary>
 /// <param name="symbolOpt">Local symbol, used by edit and continue only, null otherwise.</param>
 /// <param name="nameOpt">Name associated with the slot.</param>
 /// <param name="type">Type associated with the slot.</param>
 /// <param name="slot">Slot position in the signature.</param>
 /// <param name="synthesizedKind">Local kind.</param>
 /// <param name="id">Local id.</param>
 /// <param name="pdbAttributes">Value to emit in the attributes field in the PDB.</param>
 /// <param name="constraints">Specifies whether slot type should have pinned modifier and whether slot should have byref constraint.</param>
 /// <param name="dynamicTransformFlags">The synthesized dynamic attributes of the local.</param>
 /// <param name="tupleElementNames">Tuple element names of the local.</param>
 public LocalDefinition(
     ILocalSymbol symbolOpt,
     string nameOpt,
     Cci.ITypeReference type,
     int slot,
     SynthesizedLocalKind synthesizedKind,
     LocalDebugId id,
     LocalVariableAttributes pdbAttributes,
     LocalSlotConstraints constraints,
     ImmutableArray<TypedConstant> dynamicTransformFlags,
     ImmutableArray<TypedConstant> tupleElementNames)
 {
     _symbolOpt = symbolOpt;
     _nameOpt = nameOpt;
     _type = type;
     _slot = slot;
     _slotInfo = new LocalSlotDebugInfo(synthesizedKind, id);
     _pdbAttributes = pdbAttributes;
     _dynamicTransformFlags = dynamicTransformFlags.NullToEmpty();
     _tupleElementNames = tupleElementNames.NullToEmpty();
     _constraints = constraints;
 }
예제 #5
0
 /// <summary>
 /// Creates a new LocalDefinition.
 /// </summary>
 /// <param name="symbolOpt">Local symbol, used by edit and continue only, null otherwise.</param>
 /// <param name="nameOpt">Name associated with the slot.</param>
 /// <param name="type">Type associated with the slot.</param>
 /// <param name="slot">Slot position in the signature.</param>
 /// <param name="dynamicTransformFlags">Contains the synthesized dynamic attributes of the local</param>
 /// <param name="synthesizedKind">Local kind.</param>
 /// <param name="id">Local id.</param>
 /// <param name="pdbAttributes">Value to emit in the attributes field in the PDB.</param>
 /// <param name="constraints">Specifies whether slot type should have pinned modifier and whether slot should have byref constraint.</param>
 /// <param name="isDynamic">Specifies if the type is Dynamic.</param>
 public LocalDefinition(
     ILocalSymbol symbolOpt,
     string nameOpt,
     Cci.ITypeReference type,
     int slot,
     SynthesizedLocalKind synthesizedKind,
     LocalDebugId id,
     uint pdbAttributes,
     LocalSlotConstraints constraints,
     bool isDynamic,
     ImmutableArray<TypedConstant> dynamicTransformFlags)
 {
     _symbolOpt = symbolOpt;
     _nameOpt = nameOpt;
     _type = type;
     _slot = slot;
     _slotInfo = new LocalSlotDebugInfo(synthesizedKind, id);
     _pdbAttributes = pdbAttributes;
     _dynamicTransformFlags = dynamicTransformFlags;
     _constraints = constraints;
     _isDynamic = isDynamic;
 }
 public override void VisitLocal(ILocalSymbol symbol)
 {
     symbol.Type.Accept(this);
 }
 private static bool IsPassedAsArgument(StatementSyntax statement, SemanticModel semanticModel, ILocalSymbol identitySymbol)
 {
     if (statement == null) return false;
     var args = statement.DescendantNodes().OfKind<ArgumentSyntax>(SyntaxKind.Argument);
     foreach (var arg in args)
     {
         var argSymbol = semanticModel.GetSymbolInfo(arg.Expression).Symbol;
         if (identitySymbol.Equals(argSymbol)) return true;
     }
     return false;
 }
 private bool LocalsAreEquivalent(ILocalSymbol x, ILocalSymbol y)
 {
     return(HaveSameLocation(x, y));
 }
 private static bool IsDisposableLocalSymbol(ILocalSymbol localSymbol)
 {
     return(localSymbol != null &&
            DisposableMemberInNonDisposableClass.ImplementsIDisposable(localSymbol.Type as INamedTypeSymbol));
 }
 public static ExpressionSyntax Visit(ExpressionSyntax initializer, ILocalSymbol local, SemanticModel semanticModel)
 {
     var simplifier = new InitializerRewriter(initializer, local, semanticModel);
     return (ExpressionSyntax)simplifier.Visit(initializer);
 }
예제 #11
0
파일: Nullability.cs 프로젝트: zhangf911/ql
 /// <summary>
 /// Gets the annotated type of an ILocalSymbol.
 /// This has not yet been exposed on the public API.
 /// </summary>
 public static AnnotatedTypeSymbol GetAnnotatedType(this ILocalSymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation);
예제 #12
0
 public override void VisitLocal(ILocalSymbol symbol)
 {
     base.VisitLocal(symbol);
 }
 protected abstract TLocalDeclarationStatementSyntax GetUpdatedLocalDeclarationStatement(SyntaxGenerator generator, TLocalDeclarationStatementSyntax localDeclarationStatement, ILocalSymbol symbol);
 private int CombineHashCodes(ILocalSymbol x, int currentHash)
 {
     return(Hash.Combine(x.Locations.FirstOrDefault(), currentHash));
 }
        private static bool IsReturned(ILocalSymbol symbol, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            using (var pooled = ReturnValueWalker.Create(block, Search.TopLevel, semanticModel, cancellationToken))
            {
                foreach (var value in pooled.Item)
                {
                    var returnedSymbol = semanticModel.GetSymbolSafe(value, cancellationToken);
                    if (SymbolComparer.Equals(symbol, returnedSymbol))
                    {
                        return(true);
                    }

                    if (value is ObjectCreationExpressionSyntax objectCreation)
                    {
                        if (objectCreation.ArgumentList != null)
                        {
                            foreach (var argument in objectCreation.ArgumentList.Arguments)
                            {
                                var arg = semanticModel.GetSymbolSafe(argument.Expression, cancellationToken);
                                if (SymbolComparer.Equals(symbol, arg))
                                {
                                    return(true);
                                }
                            }
                        }

                        if (objectCreation.Initializer != null)
                        {
                            foreach (var argument in objectCreation.Initializer.Expressions)
                            {
                                var arg = semanticModel.GetSymbolSafe(argument, cancellationToken);
                                if (SymbolComparer.Equals(symbol, arg))
                                {
                                    return(true);
                                }
                            }
                        }
                    }

                    if (value is InvocationExpressionSyntax invocation)
                    {
                        if (returnedSymbol == KnownSymbol.RxDisposable.Create &&
                            invocation.ArgumentList != null &&
                            invocation.ArgumentList.Arguments.TryGetSingle(out ArgumentSyntax argument))
                        {
                            var body = (argument.Expression as ParenthesizedLambdaExpressionSyntax)?.Body;
                            using (var pooledInvocations = InvocationWalker.Create(body))
                            {
                                foreach (var candidate in pooledInvocations.Item.Invocations)
                                {
                                    if (Disposable.IsDisposing(candidate, symbol, semanticModel, cancellationToken))
                                    {
                                        return(true);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
예제 #16
0
 public static IVariableDeclaration CreateVariableDeclaration(ILocalSymbol variable, IVariableInitializer initializer, SemanticModel semanticModel, SyntaxNode syntax)
 {
     return(CreateVariableDeclaration(ImmutableArray.Create(variable), initializer, semanticModel, syntax));
 }
예제 #17
0
        private static IEnumerable <int> GetAssignedIndexes(IEnumerable <StatementSyntax> statements, ILocalSymbol symbol, SemanticModel semanticModel)
        {
            foreach (var statement in statements)
            {
                var assignment = statement as AssignmentStatementSyntax;
                if (assignment == null)
                {
                    yield break;
                }

                var invocation = assignment.Left as InvocationExpressionSyntax;
                if (invocation?.ArgumentList == null ||
                    invocation.ArgumentList.Arguments.Count != 1)
                {
                    yield break;
                }

                var assignedSymbol = semanticModel.GetSymbolInfo(invocation.Expression).Symbol;
                if (!symbol.Equals(assignedSymbol))
                {
                    yield break;
                }

                var argument = invocation.ArgumentList.Arguments.First();
                var index    = GetConstantArgumentValue(argument, semanticModel);
                if (!index.HasValue)
                {
                    yield break;
                }

                yield return(index.Value);
            }
        }
        public sealed override void VisitLocal(ILocalSymbol symbol)
        {
            Visit(symbol.Type);

            Visit(symbol.ContainingSymbol);
        }
            private async Task<IEnumerable<SymbolDisplayPart>> GetLocalPartsAsync(ILocalSymbol symbol)
            {
                if (symbol.IsConst)
                {
                    var initializerParts = await GetInitializerSourcePartsAsync(symbol).ConfigureAwait(false);
                    if (initializerParts != null)
                    {
                        var parts = ToMinimalDisplayParts(symbol, MinimallyQualifiedFormat).ToList();
                        parts.AddRange(Space());
                        parts.AddRange(Punctuation("="));
                        parts.AddRange(Space());
                        parts.AddRange(initializerParts);

                        return parts;
                    }
                }

                return ToMinimalDisplayParts(symbol, MinimallyQualifiedFormatWithConstants);
            }
        private static SyntaxNode CreateRootAddingDisposeToEndOfMethod(SyntaxNode root, ExpressionStatementSyntax statement, ILocalSymbol identitySymbol)
        {
            var method     = statement.FirstAncestorOrSelf <MethodDeclarationSyntax>();
            var newDispose = ImplementsDisposableExplicitly(identitySymbol.Type)
                ? SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression(
                                                        SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                             SyntaxFactory.ParenthesizedExpression(SyntaxFactory.CastExpression(SyntaxFactory.ParseName("System.IDisposable").WithAdditionalAnnotations(Simplifier.Annotation), SyntaxFactory.IdentifierName(identitySymbol.Name))),
                                                                                             SyntaxFactory.IdentifierName("Dispose"))))
                : SyntaxFactory.ParseStatement($"{identitySymbol.Name}.Dispose();");

            newDispose = newDispose.WithAdditionalAnnotations(Formatter.Annotation);
            var last    = method.Body.Statements.Last();
            var newRoot = root.InsertNodesAfter(method.Body.Statements.Last(), new[] { newDispose });

            return(newRoot);
        }
예제 #21
0
 public override void VisitLocal(ILocalSymbol symbol)
 {
     VisitAttributes(symbol);
     symbol.Type.Accept(this);
 }
 private static bool IsAssignedToField(ExpressionStatementSyntax expressionStatement, SemanticModel semanticModel, ILocalSymbol identitySymbol)
 {
     if (expressionStatement == null) return false;
     if (!expressionStatement.Expression.IsKind(SyntaxKind.SimpleAssignmentExpression)) return false;
     var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression;
     var assignmentTarget = semanticModel.GetSymbolInfo(assignment.Left).Symbol;
     if (assignmentTarget?.Kind != SymbolKind.Field) return false;
     var assignmentSource = semanticModel.GetSymbolInfo(assignment.Right).Symbol;
     return (identitySymbol.Equals(assignmentSource));
 }
        private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context)
        {
            if (GeneratedCodeAnalyzer?.IsGeneratedCode(context) == true)
            {
                return;
            }

            var catchClause = (CatchClauseSyntax)context.Node;

            if (catchClause.Declaration == null || catchClause.Block == null)
            {
                return;
            }

            ILocalSymbol symbol = context
                                  .SemanticModel
                                  .GetDeclaredSymbol(catchClause.Declaration, context.CancellationToken);

            if (symbol != null)
            {
                foreach (SyntaxNode node in catchClause.Block.DescendantNodes(f => !f.IsKind(SyntaxKind.CatchClause)))
                {
                    if (node.IsKind(SyntaxKind.ThrowStatement))
                    {
                        var throwStatement = (ThrowStatementSyntax)node;
                        if (throwStatement.Expression != null)
                        {
                            ISymbol expressionSymbol = context
                                                       .SemanticModel
                                                       .GetSymbolInfo(throwStatement.Expression, context.CancellationToken)
                                                       .Symbol;

                            if (expressionSymbol != null &&
                                symbol.Equals(expressionSymbol))
                            {
                                context.ReportDiagnostic(
                                    DiagnosticDescriptors.RemoveOriginalExceptionFromThrowStatement,
                                    throwStatement.Expression.GetLocation());
                            }
                        }
                    }
                }
            }

            if (catchClause.Declaration.Type != null &&
                catchClause.Block.Statements.Count == 0)
            {
                ITypeSymbol typeSymbol = context
                                         .SemanticModel
                                         .GetTypeInfo(catchClause.Declaration.Type, context.CancellationToken)
                                         .Type;

                if (typeSymbol != null)
                {
                    INamedTypeSymbol exceptionTypeSymbol = context.GetTypeByMetadataName("System.Exception");

                    if (typeSymbol.Equals(exceptionTypeSymbol))
                    {
                        context.ReportDiagnostic(
                            DiagnosticDescriptors.AvoidEmptyCatchClauseThatCatchesSystemException,
                            catchClause.CatchKeyword.GetLocation());
                    }
                }
            }
        }
예제 #24
0
		string GetLocalVariableMarkup (ILocalSymbol local)
		{
			if (local == null)
				throw new ArgumentNullException ("local");

			var result = new StringBuilder ();

			if (local.IsConst)
				result.Append (Highlight ("const ", colorStyle.KeywordModifiers));

			result.Append (GetTypeReferenceString (local.Type));
			if (BreakLineAfterReturnType) {
				result.AppendLine ();
			} else {
				result.Append (" ");
			}

			result.Append (FilterEntityName (local.Name));

			if (local.IsConst) {
				if (options.GetOption (CSharpFormattingOptions.SpacingAroundBinaryOperator) == BinaryOperatorSpacingOptions.Single) {
					result.Append (" = ");
				} else {
					result.Append ("=");
				}
				AppendConstant (result, local.Type, local.ConstantValue);
			}

			return result.ToString ();
		}
예제 #25
0
        private static bool IsEndingWithDispose(SemanticModel semanticModel, List <StatementSyntax> insideUsing, ILocalSymbol disposableLocal)
        {
            var lastInUsingAsCall = (((insideUsing.LastOrDefault() as ExpressionStatementSyntax)?.Expression as InvocationExpressionSyntax)?.Expression as MemberAccessExpressionSyntax);

            if (lastInUsingAsCall == null)
            {
                return(false);
            }

            var targetSymbol = semanticModel.GetSymbolInfo(lastInUsingAsCall.Expression);

            if (!disposableLocal.Equals(targetSymbol.Symbol))
            {
                return(false);
            }


            var dispose = semanticModel.Compilation.GetSpecialType(SpecialType.System_IDisposable).GetMembers("Dispose").Single();

            var calledMethod = semanticModel.GetSymbolInfo(lastInUsingAsCall).Symbol;

            if (!dispose.Equals(calledMethod))
            {
                return(false);
            }


            return(true);
        }
            private async Task AddDescriptionForLocalAsync(ILocalSymbol symbol)
            {
                var parts = await GetLocalPartsAsync(symbol).ConfigureAwait(false);

                AddToGroup(SymbolDescriptionGroups.MainDescription,
                    symbol.IsConst
                        ? Description(FeaturesResources.local_constant)
                        : Description(FeaturesResources.local_variable),
                    parts);
            }
예제 #27
0
        private static void ReduceUsingBlock(SemanticModel semanticModel, List <StatementSyntax> insideUsing, ILocalSymbol symbol)
        {
            for (int i = insideUsing.Count - 1; i >= 0; i--)
            {
                var flow = semanticModel.AnalyzeDataFlow(insideUsing[i]);

                if (flow.ReadInside.Contains(symbol) || flow.WrittenInside.Contains(symbol))
                {
                    break;
                }

                insideUsing.RemoveAt(i);
            }
        }
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationBlockStartAction(
                (operationBlockContext) =>
            {
                if (operationBlockContext.OwningSymbol is IMethodSymbol containingMethod)
                {
                    HashSet <ILocalSymbol> mightBecomeConstLocals = new HashSet <ILocalSymbol>();
                    HashSet <ILocalSymbol> assignedToLocals       = new HashSet <ILocalSymbol>();

                    operationBlockContext.RegisterOperationAction(
                        (operationContext) =>
                    {
                        if (operationContext.Operation is IAssignmentOperation assignment)
                        {
                            AssignTo(assignment.Target, assignedToLocals, mightBecomeConstLocals);
                        }
                        else if (operationContext.Operation is IIncrementOrDecrementOperation increment)
                        {
                            AssignTo(increment.Target, assignedToLocals, mightBecomeConstLocals);
                        }
                        else
                        {
                            throw TestExceptionUtilities.UnexpectedValue(operationContext.Operation);
                        }
                    },
                        OperationKind.SimpleAssignment,
                        OperationKind.CompoundAssignment,
                        OperationKind.Increment);

                    operationBlockContext.RegisterOperationAction(
                        (operationContext) =>
                    {
                        IInvocationOperation invocation = (IInvocationOperation)operationContext.Operation;
                        foreach (IArgumentOperation argument in invocation.Arguments)
                        {
                            if (argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref)
                            {
                                AssignTo(argument.Value, assignedToLocals, mightBecomeConstLocals);
                            }
                        }
                    },
                        OperationKind.Invocation);

                    operationBlockContext.RegisterOperationAction(
                        (operationContext) =>
                    {
                        IVariableDeclarationGroupOperation declaration = (IVariableDeclarationGroupOperation)operationContext.Operation;
                        foreach (IVariableDeclaratorOperation variable in declaration.Declarations.SelectMany(decl => decl.Declarators))
                        {
                            ILocalSymbol local = variable.Symbol;
                            if (!local.IsConst && !assignedToLocals.Contains(local))
                            {
                                var localType = local.Type;
                                if ((!localType.IsReferenceType || localType.SpecialType == SpecialType.System_String) && localType.SpecialType != SpecialType.None)
                                {
                                    IVariableInitializerOperation initializer = variable.GetVariableInitializer();
                                    if (initializer != null && initializer.Value.ConstantValue.HasValue)
                                    {
                                        mightBecomeConstLocals.Add(local);
                                    }
                                }
                            }
                        }
                    },
                        OperationKind.VariableDeclarationGroup);

                    operationBlockContext.RegisterOperationBlockEndAction(
                        (operationBlockEndContext) =>
                    {
                        foreach (ILocalSymbol couldBeConstLocal in mightBecomeConstLocals)
                        {
                            Report(operationBlockEndContext, couldBeConstLocal, LocalCouldBeConstDescriptor);
                        }
                    });
                }
            });
        }
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterCompilationStartAction(
                (compilationContext) =>
            {
                Dictionary <IFieldSymbol, HashSet <INamedTypeSymbol> > fieldsSourceTypes = new Dictionary <IFieldSymbol, HashSet <INamedTypeSymbol> >();

                compilationContext.RegisterOperationBlockStartAction(
                    (operationBlockContext) =>
                {
                    if (operationBlockContext.OwningSymbol is IMethodSymbol containingMethod)
                    {
                        Dictionary <ILocalSymbol, HashSet <INamedTypeSymbol> > localsSourceTypes = new Dictionary <ILocalSymbol, HashSet <INamedTypeSymbol> >();

                        // Track explicit assignments.
                        operationBlockContext.RegisterOperationAction(
                            (operationContext) =>
                        {
                            if (operationContext.Operation is IAssignmentOperation assignment)
                            {
                                AssignTo(assignment.Target, localsSourceTypes, fieldsSourceTypes, assignment.Value);
                            }
                            else if (operationContext.Operation is IIncrementOrDecrementOperation increment)
                            {
                                SyntaxNode syntax = increment.Syntax;
                                ITypeSymbol type  = increment.Type;
                                Optional <object> constantValue = new Optional <object>(1);
                                bool isImplicit = increment.IsImplicit;
                                var value       = new LiteralOperation(operationContext.Compilation.GetSemanticModel(syntax.SyntaxTree), syntax, type, constantValue, isImplicit);

                                AssignTo(increment.Target, localsSourceTypes, fieldsSourceTypes, value);
                            }
                            else
                            {
                                throw TestExceptionUtilities.UnexpectedValue(operationContext.Operation);
                            }
                        },
                            OperationKind.SimpleAssignment,
                            OperationKind.CompoundAssignment,
                            OperationKind.Increment);

                        // Track arguments that match out or ref parameters.
                        operationBlockContext.RegisterOperationAction(
                            (operationContext) =>
                        {
                            IInvocationOperation invocation = (IInvocationOperation)operationContext.Operation;
                            foreach (IArgumentOperation argument in invocation.Arguments)
                            {
                                if (argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref)
                                {
                                    AssignTo(argument.Value, localsSourceTypes, fieldsSourceTypes, argument.Parameter.Type);
                                }
                            }
                        },
                            OperationKind.Invocation);

                        // Track local variable initializations.
                        operationBlockContext.RegisterOperationAction(
                            (operationContext) =>
                        {
                            IVariableInitializerOperation initializer = (IVariableInitializerOperation)operationContext.Operation;
                            // If the parent is a single variable declaration, just process that one variable. If it's a multi variable
                            // declaration, process all variables being assigned
                            if (initializer.Parent is IVariableDeclaratorOperation singleVariableDeclaration)
                            {
                                ILocalSymbol local = singleVariableDeclaration.Symbol;
                                AssignTo(local, local.Type, localsSourceTypes, initializer.Value);
                            }
                            else if (initializer.Parent is IVariableDeclarationOperation multiVariableDeclaration)
                            {
                                foreach (ILocalSymbol local in multiVariableDeclaration.GetDeclaredVariables())
                                {
                                    AssignTo(local, local.Type, localsSourceTypes, initializer.Value);
                                }
                            }
                        },
                            OperationKind.VariableInitializer);

                        // Report locals that could have more specific types.
                        operationBlockContext.RegisterOperationBlockEndAction(
                            (operationBlockEndContext) =>
                        {
                            foreach (ILocalSymbol local in localsSourceTypes.Keys)
                            {
                                if (HasMoreSpecificSourceType(local, local.Type, localsSourceTypes, out var mostSpecificSourceType))
                                {
                                    Report(operationBlockEndContext, local, mostSpecificSourceType, LocalCouldHaveMoreSpecificTypeDescriptor);
                                }
                            }
                        });
                    }
                });

                // Track field initializations.
                compilationContext.RegisterOperationAction(
                    (operationContext) =>
                {
                    IFieldInitializerOperation initializer = (IFieldInitializerOperation)operationContext.Operation;
                    foreach (IFieldSymbol initializedField in initializer.InitializedFields)
                    {
                        AssignTo(initializedField, initializedField.Type, fieldsSourceTypes, initializer.Value);
                    }
                },
                    OperationKind.FieldInitializer);

                // Report fields that could have more specific types.
                compilationContext.RegisterCompilationEndAction(
                    (compilationEndContext) =>
                {
                    foreach (IFieldSymbol field in fieldsSourceTypes.Keys)
                    {
                        if (HasMoreSpecificSourceType(field, field.Type, fieldsSourceTypes, out var mostSpecificSourceType))
                        {
                            Report(compilationEndContext, field, mostSpecificSourceType, FieldCouldHaveMoreSpecificTypeDescriptor);
                        }
                    }
                });
            });
        }
예제 #30
0
 /// <summary>
 /// Retrieve a local slot by its symbol.
 /// </summary>
 internal LocalDefinition GetLocal(ILocalSymbol symbol)
 {
     return(LocalMap[symbol]);
 }
예제 #31
0
 public VariableDeclaration(ILocalSymbol variable, IExpression initialValue, SyntaxNode syntax)
 {
     Variable     = variable;
     InitialValue = initialValue;
     Syntax       = syntax;
 }
예제 #32
0
 public virtual void VisitLocal(ILocalSymbol symbol)
 {
     DefaultVisit(symbol);
 }
예제 #33
0
 private static string GetClassificationForLocal(ILocalSymbol localSymbol)
 {
     return(localSymbol.IsConst
         ? ClassificationTypeNames.ConstantName
         : ClassificationTypeNames.LocalName);
 }
예제 #34
0
 public VariableDeclaration(ILocalSymbol variable, IExpression initialValue, SyntaxNode syntax)
 {
     Variable = variable;
     InitialValue = initialValue;
     Syntax = syntax;
 }
예제 #35
0
        private static bool TryAnalyze(
            SemanticModel semanticModel,
            ILocalSymbol local,
            TypeSyntax typeNode,
            SyntaxToken identifier,
            Conversion conversion,
            SyntaxNode searchScope,
            [NotNullWhen(true)] out INamedTypeSymbol?tupleType,
            out ImmutableArray <MemberAccessExpressionSyntax> memberAccessExpressions,
            CancellationToken cancellationToken)
        {
            tupleType = null;
            memberAccessExpressions = default;

            if (identifier.IsMissing)
            {
                return(false);
            }

            if (!IsViableTupleTypeSyntax(typeNode))
            {
                return(false);
            }

            if (conversion.Exists &&
                !conversion.IsIdentity &&
                !conversion.IsTupleConversion &&
                !conversion.IsTupleLiteralConversion)
            {
                // If there is any other conversion, we bail out because the source type might not be a tuple
                // or it is a tuple but only thanks to target type inference, which won't occur in a deconstruction.
                // Interesting case that illustrates this is initialization with a default literal:
                // (int a, int b) t = default;
                // This is classified as conversion.IsNullLiteral.
                return(false);
            }

            var type = semanticModel.GetTypeInfo(typeNode, cancellationToken).Type;

            if (type == null || !type.IsTupleType)
            {
                return(false);
            }

            tupleType = (INamedTypeSymbol)type;
            if (tupleType.TupleElements.Length < 2)
            {
                return(false);
            }

            // All tuple elements must have been explicitly provided by the user.
            foreach (var element in tupleType.TupleElements)
            {
                if (element.IsImplicitlyDeclared)
                {
                    return(false);
                }
            }

            using var _ = ArrayBuilder <MemberAccessExpressionSyntax> .GetInstance(out var references);

            // If the user actually uses the tuple local for anything other than accessing
            // fields off of it, then we can't deconstruct this tuple into locals.
            if (!OnlyUsedToAccessTupleFields(
                    semanticModel, searchScope, local, references, cancellationToken))
            {
                return(false);
            }

            // Can only deconstruct the tuple if the names we introduce won't collide
            // with anything else in scope (either outside, or inside the method).
            if (AnyTupleFieldNamesCollideWithExistingNames(
                    semanticModel, tupleType, searchScope, cancellationToken))
            {
                return(false);
            }

            memberAccessExpressions = references.ToImmutable();
            return(true);
        }
예제 #36
0
        public override void VisitLocal(ILocalSymbol symbol)
        {
            if (format.LocalOptions.IncludesOption(SymbolDisplayLocalOptions.IncludeType))
            {
                symbol.Type.Accept(this);
                AddSpace();
            }

            builder.Add(CreatePart(SymbolDisplayPartKind.LocalName, symbol, symbol.Name));

            if (symbol.IsConst &&
                symbol.HasConstantValue &&
                format.LocalOptions.IncludesOption(SymbolDisplayLocalOptions.IncludeConstantValue) &&
                CanAddConstant(symbol.Type, symbol.ConstantValue))
            {
                AddSpace();
                AddPunctuation(SyntaxKind.EqualsToken);
                AddSpace();

                AddConstantValue(symbol.Type, symbol.ConstantValue);
            }
        }
예제 #37
0
 protected override bool CanMoveToBlock(ILocalSymbol localSymbol, SyntaxNode currentBlock, SyntaxNode destinationBlock)
 => localSymbol.CanSafelyMoveLocalToBlock(currentBlock, destinationBlock);
예제 #38
0
 private void Report(OperationBlockAnalysisContext context, ILocalSymbol local, DiagnosticDescriptor descriptor)
 {
     context.ReportDiagnostic(Diagnostic.Create(descriptor, local.Locations.FirstOrDefault()));
 }
예제 #39
0
 public virtual void VisitLocal(ILocalSymbol symbol)
 {
     DefaultVisit(symbol);
 }
 private bool LocalsAreEquivalent(ILocalSymbol x, ILocalSymbol y)
 {
     return HaveSameLocation(x, y);
 }
 public override void VisitLocal(ILocalSymbol symbol)
 {
     symbol.Type.Accept(this);
 }
        private static IEnumerable<int> GetAssignedIndexes(IEnumerable<StatementSyntax> statements, ILocalSymbol symbol, SemanticModel semanticModel)
        {
            foreach (var statement in statements)
            {
                var assignment = statement as AssignmentStatementSyntax;
                if (assignment == null)
                {
                    yield break;
                }

                var invocation = assignment.Left as InvocationExpressionSyntax;
                if (invocation?.ArgumentList == null ||
                    invocation.ArgumentList.Arguments.Count != 1)
                {
                    yield break;
                }

                var assignedSymbol = semanticModel.GetSymbolInfo(invocation.Expression).Symbol;
                if (!symbol.Equals(assignedSymbol))
                {
                    yield break;
                }

                var argument = invocation.ArgumentList.Arguments.First();
                var index = GetConstantArgumentValue(argument, semanticModel);
                if (!index.HasValue)
                {
                    yield break;
                }

                yield return index.Value;
            }
        }
예제 #43
0
 private LoopDeclarationVerifier(ForStatementSyntax forStatement, SemanticModel semanticModel, ILocalSymbol loopIndex)
 {
     _forStatement  = forStatement;
     _semanticModel = semanticModel;
     _loopIndex     = loopIndex;
 }
 private static bool IsReturned(MethodDeclarationSyntax method, StatementSyntax statement, SemanticModel semanticModel, ILocalSymbol identitySymbol)
 {
     var anonymousFunction = statement.FirstAncestorOfKind(SyntaxKind.ParenthesizedLambdaExpression,
         SyntaxKind.SimpleLambdaExpression, SyntaxKind.AnonymousMethodExpression) as AnonymousFunctionExpressionSyntax;
     IMethodSymbol methodSymbol;
     BlockSyntax body;
     if (anonymousFunction != null)
     {
         methodSymbol = semanticModel.GetSymbolInfo(anonymousFunction).Symbol as IMethodSymbol;
         body = anonymousFunction.Body as BlockSyntax;
     }
     else
     {
         methodSymbol = semanticModel.GetDeclaredSymbol(method);
         body = method.Body;
     }
     if (body == null) return true;
     var returnExpressions = body.DescendantNodes().OfType<ReturnStatementSyntax>().Select(r => r.Expression);
     var returnTypeSymbol = methodSymbol?.ReturnType;
     if (returnTypeSymbol == null) return false;
     if (returnTypeSymbol.SpecialType == SpecialType.System_Void) return false;
     var isReturning = returnExpressions.Any(returnExpression =>
     {
         var returnSymbol = semanticModel.GetSymbolInfo(returnExpression).Symbol;
         if (returnSymbol == null) return false;
         return returnSymbol.Equals(identitySymbol);
     });
     return isReturning;
 }
예제 #45
0
 public override bool VisitLocal(ILocalSymbol symbol)
 {
     return(Visit(symbol.Type));
 }
 private static bool IsCorrectDispose(ExpressionStatementSyntax expressionStatement, SemanticModel semanticModel, ILocalSymbol identitySymbol)
 {
     if (expressionStatement == null) return false;
     var invocation = expressionStatement.Expression as InvocationExpressionSyntax;
     if (invocation?.ArgumentList.Arguments.Any() ?? true) return false;
     var memberAccess = invocation.Expression as MemberAccessExpressionSyntax;
     if (memberAccess == null) return false;
     ISymbol memberSymbol;
     if (memberAccess.Expression.IsKind(SyntaxKind.IdentifierName))
     {
         memberSymbol = semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol;
     }
     else if (memberAccess.Expression.IsKind(SyntaxKind.ParenthesizedExpression))
     {
         var parenthesizedExpression = (ParenthesizedExpressionSyntax)memberAccess.Expression;
         var cast = parenthesizedExpression.Expression as CastExpressionSyntax;
         if (cast == null) return false;
         var catTypeSymbol = semanticModel.GetTypeInfo(cast.Type).Type;
         if (catTypeSymbol.SpecialType != SpecialType.System_IDisposable) return false;
         memberSymbol = semanticModel.GetSymbolInfo(cast.Expression).Symbol;
     }
     else return false;
     if (memberSymbol == null || !memberSymbol.Equals(identitySymbol)) return false;
     var memberAccessed = memberAccess.Name as IdentifierNameSyntax;
     if (memberAccessed == null) return false;
     if (memberAccessed.Identifier.Text != "Dispose" || memberAccessed.Arity != 0) return false;
     var methodSymbol = semanticModel.GetSymbolInfo(memberAccessed).Symbol as IMethodSymbol;
     if (methodSymbol == null) return false;
     if (methodSymbol.ToString() == "System.IDisposable.Dispose()") return true;
     var disposeMethod = (IMethodSymbol)semanticModel.Compilation.GetSpecialType(SpecialType.System_IDisposable).GetMembers("Dispose").Single();
     var isDispose = methodSymbol.Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(disposeMethod));
     return isDispose;
 }
예제 #47
0
        private static void GetInterfaceInfo(
            SemanticModel model,
            ILocalSymbol foreachVariable,
            IOperation foreachCollection,
            out ITypeSymbol explicitCastInterface,
            out string collectionNameSuggestion,
            out string countName
            )
        {
            explicitCastInterface    = null;
            collectionNameSuggestion = null;
            countName = null;

            // go through list of types and interfaces to find out right set;
            var foreachType = foreachVariable.Type;

            if (IsNullOrErrorType(foreachType))
            {
                return;
            }

            var collectionType = foreachCollection.Type;

            if (IsNullOrErrorType(collectionType))
            {
                return;
            }

            // go through explicit types first.

            // check array case
            if (collectionType is IArrayTypeSymbol array)
            {
                if (array.Rank != 1)
                {
                    // array type supports IList and other interfaces, but implementation
                    // only supports Rank == 1 case. other case, it will throw on runtime
                    // even if there is no error on compile time.
                    // we explicitly mark that we only support Rank == 1 case
                    return;
                }

                if (!IsExchangable(array.ElementType, foreachType, model.Compilation))
                {
                    return;
                }

                collectionNameSuggestion = "array";
                explicitCastInterface    = null;
                countName = Length;
                return;
            }

            // check string case
            if (collectionType.SpecialType == SpecialType.System_String)
            {
                var charType = model.Compilation.GetSpecialType(SpecialType.System_Char);
                if (!IsExchangable(charType, foreachType, model.Compilation))
                {
                    return;
                }

                collectionNameSuggestion = "str";
                explicitCastInterface    = null;
                countName = Length;
                return;
            }

            // check ImmutableArray case
            if (
                collectionType.OriginalDefinition.Equals(
                    model.Compilation.GetTypeByMetadataName(typeof(ImmutableArray <>).FullName)
                    )
                )
            {
                var indexer = GetInterfaceMember(collectionType, get_Item);
                if (indexer != null)
                {
                    if (!IsExchangable(indexer.ReturnType, foreachType, model.Compilation))
                    {
                        return;
                    }

                    collectionNameSuggestion = "array";
                    explicitCastInterface    = null;
                    countName = Length;
                    return;
                }
            }

            // go through all known interfaces we support next.
            var knownCollectionInterfaces = s_KnownInterfaceNames
                                            .Select(s => model.Compilation.GetTypeByMetadataName(s))
                                            .Where(t => !IsNullOrErrorType(t));

            // for all interfaces, we suggest collection name as "list"
            collectionNameSuggestion = "list";

            // check type itself is interface case
            if (
                collectionType.TypeKind == TypeKind.Interface &&
                knownCollectionInterfaces.Contains(collectionType.OriginalDefinition)
                )
            {
                var indexer = GetInterfaceMember(collectionType, get_Item);
                if (
                    indexer != null &&
                    IsExchangable(indexer.ReturnType, foreachType, model.Compilation)
                    )
                {
                    explicitCastInterface = null;
                    countName             = Count;
                    return;
                }
            }

            // check regular cases (implicitly implemented)
            ITypeSymbol explicitInterface = null;

            foreach (var current in collectionType.AllInterfaces)
            {
                if (!knownCollectionInterfaces.Contains(current.OriginalDefinition))
                {
                    continue;
                }

                // see how the type implements the interface
                var countSymbol   = GetInterfaceMember(current, get_Count);
                var indexerSymbol = GetInterfaceMember(current, get_Item);
                if (countSymbol == null || indexerSymbol == null)
                {
                    continue;
                }

                if (
                    !(
                        collectionType.FindImplementationForInterfaceMember(countSymbol)
                        is IMethodSymbol countImpl
                        ) ||
                    !(
                        collectionType.FindImplementationForInterfaceMember(indexerSymbol)
                        is IMethodSymbol indexerImpl
                        )
                    )
                {
                    continue;
                }

                if (!IsExchangable(indexerImpl.ReturnType, foreachType, model.Compilation))
                {
                    continue;
                }

                // implicitly implemented!
                if (
                    countImpl.ExplicitInterfaceImplementations.IsEmpty &&
                    indexerImpl.ExplicitInterfaceImplementations.IsEmpty
                    )
                {
                    explicitCastInterface = null;
                    countName             = Count;
                    return;
                }

                if (explicitInterface == null)
                {
                    explicitInterface = current;
                }
            }

            // okay, we don't have implicitly implemented one, but we do have explicitly implemented one
            if (explicitInterface != null)
            {
                explicitCastInterface = explicitInterface;
                countName             = Count;
            }
        }
 private static bool IsReturned(MethodDeclarationSyntax method, SemanticModel semanticModel, ILocalSymbol identitySymbol)
 {
     var returnTypeSymbol = semanticModel.GetTypeInfo(method.ReturnType).Type;
     if (returnTypeSymbol == null) return false;
     if (returnTypeSymbol.SpecialType == SpecialType.System_Void || !returnTypeSymbol.Equals(identitySymbol.Type)) return false;
     var returns = method.Body.DescendantNodes().OfType<ReturnStatementSyntax>();
     var isReturning = returns.Any(r =>
     {
         var returnSymbol = semanticModel.GetSymbolInfo(r.Expression).Symbol;
         if (returnSymbol == null) return false;
         return returnSymbol.Equals(identitySymbol);
     });
     return isReturning;
 }
예제 #49
0
 protected abstract bool IsSupported(
     ILocalSymbol foreachVariable,
     IForEachLoopOperation forEachOperation,
     TForEachStatement foreachStatement
     );
 private InitializerRewriter(ExpressionSyntax initializer, ILocalSymbol localSymbol, SemanticModel semanticModel)
 {
     _semanticModel = semanticModel;
     _localSymbol = localSymbol;
     _initializer = initializer;
 }
            private async Task <ImmutableArray <SymbolDisplayPart> > GetLocalPartsAsync(ILocalSymbol symbol)
            {
                if (symbol.IsConst)
                {
                    var initializerParts = await GetInitializerSourcePartsAsync(symbol).ConfigureAwait(false);

                    if (initializerParts != null)
                    {
                        var parts = ArrayBuilder <SymbolDisplayPart> .GetInstance();

                        parts.AddRange(ToMinimalDisplayParts(symbol, MinimallyQualifiedFormat));
                        parts.AddRange(Space());
                        parts.AddRange(Punctuation("="));
                        parts.AddRange(Space());
                        parts.AddRange(initializerParts);

                        return(parts.ToImmutableAndFree());
                    }
                }

                return(ToMinimalDisplayParts(symbol, MinimallyQualifiedFormatWithConstants));
            }
예제 #52
0
 public override object VisitLocal(ILocalSymbol localSymbol)
 {
     WriteType(SymbolKeyType.BodyLevel);
     BodyLevelSymbolKey.Create(localSymbol, this);
     return(null);
 }
 private void Report(OperationBlockAnalysisContext context, ILocalSymbol local, DiagnosticDescriptor descriptor)
 {
     context.ReportDiagnostic(Diagnostic.Create(descriptor, local.Locations.FirstOrDefault()));
 }
            private async Task<ImmutableArray<SymbolDisplayPart>> GetLocalPartsAsync(ILocalSymbol symbol)
            {
                if (symbol.IsConst)
                {
                    var initializerParts = await GetInitializerSourcePartsAsync(symbol).ConfigureAwait(false);
                    if (initializerParts != null)
                    {
                        var parts = ArrayBuilder<SymbolDisplayPart>.GetInstance();
                        parts.AddRange(ToMinimalDisplayParts(symbol, MinimallyQualifiedFormat));
                        parts.AddRange(Space());
                        parts.AddRange(Punctuation("="));
                        parts.AddRange(Space());
                        parts.AddRange(initializerParts);

                        return parts.ToImmutableAndFree();
                    }
                }

                return ToMinimalDisplayParts(symbol, MinimallyQualifiedFormatWithConstants);
            }
 public RecursiveIsNewlyCreatedObjectState Add(ILocalSymbol variable) => new RecursiveIsNewlyCreatedObjectState(VariablesUnderTest.Add(variable));