示例#1
0
 public static SerializerTypeAnalyzer Create(WellKnownTypes wellKnownTypes) => new SerializerTypeAnalyzer(
     wellKnownTypes.CopierMethodAttribute,
     wellKnownTypes.SerializerMethodAttribute,
     wellKnownTypes.DeserializerMethodAttribute,
     wellKnownTypes.SerializerAttribute);
示例#2
0
 public SerializerGenerator(CodeGeneratorOptions options, WellKnownTypes wellKnownTypes)
 {
     this.options        = options;
     this.wellKnownTypes = wellKnownTypes;
 }
示例#3
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.RegisterCompilationStartAction(compilationContext =>
            {
                var iDisposable = WellKnownTypes.IDisposable(compilationContext.Compilation);
                if (iDisposable == null)
                {
                    return;
                }

                var iCollection        = WellKnownTypes.ICollection(compilationContext.Compilation);
                var genericICollection = WellKnownTypes.GenericICollection(compilationContext.Compilation);
                var disposeOwnershipTransferLikelyTypes = GetDisposeOwnershipTransferLikelyTypes(compilationContext.Compilation);
                compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext =>
                {
                    bool hasDisposableCreation = false;
                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        if (!hasDisposableCreation &&
                            operationContext.Operation.Type.IsDisposable(iDisposable))
                        {
                            hasDisposableCreation = true;
                        }
                    },
                                                                       OperationKind.ObjectCreation,
                                                                       OperationKind.TypeParameterObjectCreation,
                                                                       OperationKind.DynamicObjectCreation,
                                                                       OperationKind.Invocation);

                    operationBlockStartContext.RegisterOperationBlockEndAction(operationBlockEndContext =>
                    {
                        if (!hasDisposableCreation ||
                            !(operationBlockEndContext.OwningSymbol is IMethodSymbol containingMethod))
                        {
                            return;
                        }

                        foreach (var operationRoot in operationBlockEndContext.OperationBlocks)
                        {
                            IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock();
                            if (topmostBlock != null)
                            {
                                var cfg = ControlFlowGraph.Create(topmostBlock);
                                var nullAnalysisResult     = NullAnalysis.GetOrComputeResult(cfg, containingMethod.ContainingType);
                                var pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod.ContainingType, nullAnalysisResult);
                                var disposeAnalysisResult  = DisposeAnalysis.GetOrComputeResult(cfg, iDisposable, iCollection,
                                                                                                genericICollection, disposeOwnershipTransferLikelyTypes, containingMethod.ContainingType, pointsToAnalysisResult, nullAnalysisResult);
                                ImmutableDictionary <AbstractLocation, DisposeAbstractValue> disposeDataAtExit = disposeAnalysisResult[cfg.Exit].InputData;
                                foreach (var kvp in disposeDataAtExit)
                                {
                                    AbstractLocation location         = kvp.Key;
                                    DisposeAbstractValue disposeValue = kvp.Value;
                                    if (disposeValue.Kind == DisposeAbstractValueKind.NotDisposed ||
                                        ((disposeValue.Kind == DisposeAbstractValueKind.Disposed ||
                                          disposeValue.Kind == DisposeAbstractValueKind.MaybeDisposed) &&
                                         disposeValue.DisposingOperations.Count > 0 &&
                                         disposeValue.DisposingOperations.All(d => d.IsInsideCatchClause())))
                                    {
                                        Debug.Assert(location.CreationOpt != null);

                                        // CA2000: In method '{0}', call System.IDisposable.Dispose on object created by '{1}' before all references to it are out of scope.
                                        var arg1       = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                                        var arg2       = location.CreationOpt.Syntax.ToString();
                                        var diagnostic = location.CreationOpt.Syntax.CreateDiagnostic(Rule, arg1, arg2);
                                        operationBlockEndContext.ReportDiagnostic(diagnostic);
                                    }
                                }

                                break;
                            }
                        }
                    });
                });
            });
        }
示例#4
0
        public override void Initialize(AnalysisContext context)
        {
            // TODO: Consider making this analyzer thread-safe.
            //context.EnableConcurrentExecution();

            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationStartContext =>
            {
                INamedTypeSymbol eventsArgSymbol = compilationStartContext.Compilation.GetTypeByMetadataName("System.EventArgs");

                // Ignore conditional methods (FxCop compat - One conditional will often call another conditional method as its only use of a parameter)
                INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationStartContext.Compilation);

                // Ignore methods with special serialization attributes (FxCop compat - All serialization methods need to take 'StreamingContext')
                INamedTypeSymbol onDeserializingAttribute = WellKnownTypes.OnDeserializingAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onDeserializedAttribute  = WellKnownTypes.OnDeserializedAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onSerializingAttribute   = WellKnownTypes.OnSerializingAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onSerializedAttribute    = WellKnownTypes.OnSerializedAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol obsoleteAttribute        = WellKnownTypes.ObsoleteAttribute(compilationStartContext.Compilation);

                ImmutableHashSet <INamedTypeSymbol> attributeSetForMethodsToIgnore = ImmutableHashSet.Create(
                    conditionalAttributeSymbol,
                    onDeserializedAttribute,
                    onDeserializingAttribute,
                    onSerializedAttribute,
                    onSerializingAttribute,
                    obsoleteAttribute);

                ImmutableHashSet <INamedTypeSymbol> exceptionsToSkip = ImmutableHashSet.Create(
                    WellKnownTypes.NotImplementedException(compilationStartContext.Compilation),
                    WellKnownTypes.NotSupportedException(compilationStartContext.Compilation));

                UnusedParameterDictionary unusedMethodParameters = new ConcurrentDictionary <IMethodSymbol, ISet <IParameterSymbol> >();
                ISet <IMethodSymbol> methodsUsedAsDelegates      = new HashSet <IMethodSymbol>();

                // Create a list of functions to exclude from analysis. We assume that any function that is used in an IMethodBindingExpression
                // cannot have its signature changed, and add it to the list of methods to be excluded from analysis.
                compilationStartContext.RegisterOperationAction(operationContext =>
                {
                    var methodBinding = (IMethodReferenceOperation)operationContext.Operation;
                    methodsUsedAsDelegates.Add(methodBinding.Method.OriginalDefinition);
                }, OperationKind.MethodReference);

                compilationStartContext.RegisterOperationBlockStartAction(startOperationBlockContext =>
                {
                    // We only care about methods.
                    if (startOperationBlockContext.OwningSymbol.Kind != SymbolKind.Method)
                    {
                        return;
                    }

                    // We only care about methods with parameters.
                    var method = (IMethodSymbol)startOperationBlockContext.OwningSymbol;
                    if (method.Parameters.IsEmpty)
                    {
                        return;
                    }

                    // Ignore implicitly declared methods, extern methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat).
                    if (method.IsImplicitlyDeclared ||
                        method.IsExtern ||
                        method.IsAbstract ||
                        method.IsVirtual ||
                        method.IsOverride ||
                        method.IsImplementationOfAnyInterfaceMember() ||
                        method.IsFinalizer())
                    {
                        return;
                    }

                    // Ignore event handler methods "Handler(object, MyEventArgs)"
                    if (eventsArgSymbol != null &&
                        method.Parameters.Length == 2 &&
                        method.Parameters[0].Type.SpecialType == SpecialType.System_Object &&
                        method.Parameters[1].Type.Inherits(eventsArgSymbol))
                    {
                        return;
                    }

                    // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'.
                    if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass)))
                    {
                        return;
                    }

                    // Ignore methods that were used as delegates
                    if (methodsUsedAsDelegates.Contains(method))
                    {
                        return;
                    }

                    // Initialize local mutable state in the start action.
                    var analyzer = new UnusedParametersAnalyzer(method, unusedMethodParameters, exceptionsToSkip);

                    // Register an intermediate non-end action that accesses and modifies the state.
                    startOperationBlockContext.RegisterOperationAction(analyzer.AnalyzeOperation, OperationKind.ParameterReference);

                    // Register an end action to add unused parameters to the unusedMethodParameters dictionary
                    startOperationBlockContext.RegisterOperationBlockEndAction(analyzer.OperationBlockEndAction);
                });

                // Register a compilation end action to filter all methods used as delegates and report any diagnostics
                compilationStartContext.RegisterCompilationEndAction(compilationAnalysisContext =>
                {
                    // Report diagnostics for unused parameters.
                    var unusedParameters = unusedMethodParameters.Where(kvp => !methodsUsedAsDelegates.Contains(kvp.Key)).SelectMany(kvp => kvp.Value);
                    foreach (var parameter in unusedParameters)
                    {
                        var diagnostic = Diagnostic.Create(Rule, parameter.Locations[0], parameter.Name, parameter.ContainingSymbol.Name);
                        compilationAnalysisContext.ReportDiagnostic(diagnostic);
                    }
                });
            });
        }
示例#5
0
 internal NamedTypeSymbol GetWellKnownType(WellKnownType type)
 {
     return(this.GetTypeByMetadataName(WellKnownTypes.GetMetadataName(type)));
 }
示例#6
0
        internal static bool IsOrleansShallowCopyable(WellKnownTypes wellKnownTypes, ITypeSymbol type)
        {
            var root = new HashSet <ITypeSymbol>();

            return(IsOrleansShallowCopyable(wellKnownTypes, type, root));
        }
        public sealed override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

            // Security analyzer - analyze and report diagnostics on generated code.
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                var compilation = compilationStartAnalysisContext.Compilation;
                var serializableAttributeTypeSymbol = WellKnownTypes.SerializableAttribute(compilation);

                if (serializableAttributeTypeSymbol == null)
                {
                    return;
                }

                var nonSerializedAttribute = WellKnownTypes.NonSerializedAttribute(compilation);
                var visitedType            = new ConcurrentDictionary <ITypeSymbol, bool>();
                var pointerFields          = new ConcurrentDictionary <IFieldSymbol, bool>();

                compilationStartAnalysisContext.RegisterSymbolAction(
                    (SymbolAnalysisContext symbolAnalysisContext) =>
                {
                    LookForSerializationWithPointerFields((ITypeSymbol)symbolAnalysisContext.Symbol, null);
                }, SymbolKind.NamedType);

                compilationStartAnalysisContext.RegisterCompilationEndAction(
                    (CompilationAnalysisContext compilationAnalysisContext) =>
                {
                    foreach (var pointerField in pointerFields.Keys)
                    {
                        var associatedSymbol = pointerField.AssociatedSymbol;
                        compilationAnalysisContext.ReportDiagnostic(
                            pointerField.CreateDiagnostic(
                                Rule,
                                associatedSymbol == null ? pointerField.Name : associatedSymbol.Name));
                    }
                });

                // Look for serialization of a type with valid pointer fields directly and indirectly.
                //
                // typeSymbol: The symbol of the type to be analyzed
                // relatedFieldSymbol: When relatedFieldSymbol is null, traverse all descendants of typeSymbol to
                //     find pointer fields; otherwise, traverse to find if relatedFieldSymbol is a pointer field
                void LookForSerializationWithPointerFields(ITypeSymbol typeSymbol, IFieldSymbol relatedFieldSymbol)
                {
                    if (typeSymbol is IPointerTypeSymbol pointerTypeSymbol)
                    {
                        // If the field is a valid pointer.
                        if (pointerTypeSymbol.PointedAtType.TypeKind == TypeKind.Struct ||
                            pointerTypeSymbol.PointedAtType.TypeKind == TypeKind.Pointer)
                        {
                            pointerFields.TryAdd(relatedFieldSymbol, true);
                        }
                    }
                    else if (typeSymbol is INamedTypeSymbol namedTypeSymbol)
                    {
                        // If it is defined in source and not visited,
                        // mark it as visited and analyze all fields of it.
                        if (namedTypeSymbol.IsInSource() &&
                            namedTypeSymbol.HasAttribute(serializableAttributeTypeSymbol) &&
                            visitedType.TryAdd(namedTypeSymbol, true))
                        {
                            // Get all the fields can be serialized.
                            var fields = namedTypeSymbol.GetMembers().OfType <IFieldSymbol>().Where(s => (nonSerializedAttribute == null ||
                                                                                                          !s.HasAttribute(nonSerializedAttribute)) &&
                                                                                                    !s.IsStatic);

                            foreach (var field in fields)
                            {
                                LookForSerializationWithPointerFields(field.Type, field);
                            }
                        }

                        // If it is a generic type, analyze all type arguments of it.
                        if (namedTypeSymbol.IsGenericType)
                        {
                            foreach (var arg in namedTypeSymbol.TypeArguments)
                            {
                                LookForSerializationWithPointerFields(arg, relatedFieldSymbol);
                            }
                        }
                    }
                    else if (typeSymbol is IArrayTypeSymbol arrayTypeSymbol)
                    {
                        LookForSerializationWithPointerFields(arrayTypeSymbol.ElementType, relatedFieldSymbol);
                    }
                }
            });
        }
示例#8
0
        public void Execute(GeneratorExecutionContext context)
        {
            var cancellationToken = context.CancellationToken;
            var compilation       = context.Compilation;
            Action <Diagnostic> reportDiagnostic = context.ReportDiagnostic;

            if (!WellKnownTypes.TryCreate(compilation, reportDiagnostic, out var wellKnownTypes))
            {
                return;
            }

            var registrationCalculator = new RegistrationCalculator(compilation, wellKnownTypes, reportDiagnostic, cancellationToken);

            foreach (var syntaxTree in context.Compilation.SyntaxTrees)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var semanticModel = context.Compilation.GetSemanticModel(syntaxTree);
                var modules       = syntaxTree.GetRoot(cancellationToken).DescendantNodesAndSelf().OfType <ClassDeclarationSyntax>()
                                    .Select(x => semanticModel.GetDeclaredSymbol(x, cancellationToken))
                                    .OfType <INamedTypeSymbol>()
                                    .Select(x =>
                {
                    var isContainer = x.AllInterfaces.Any(x
                                                          => x.OriginalDefinition.Equals(wellKnownTypes.IContainer, SymbolEqualityComparer.Default) ||
                                                          x.OriginalDefinition.Equals(wellKnownTypes.IAsyncContainer, SymbolEqualityComparer.Default));
                    return(type: x, isContainer);
                })
                                    .Where(x =>
                                           x.isContainer ||
                                           x.type.GetAttributes().Any(x =>
                                                                      x.AttributeClass is { } attribute&&
                                                                      (attribute.Equals(wellKnownTypes.RegisterAttribute, SymbolEqualityComparer.Default) ||
                                                                       attribute.Equals(wellKnownTypes.RegisterModuleAttribute, SymbolEqualityComparer.Default) ||
                                                                       attribute.Equals(wellKnownTypes.RegisterFactoryAttribute, SymbolEqualityComparer.Default) ||
                                                                       attribute.Equals(wellKnownTypes.RegisterDecoratorAttribute, SymbolEqualityComparer.Default))) ||
                                           x.type.GetMembers().Any(x => x.GetAttributes().Any(x =>
                                                                                              x.AttributeClass is { } attribute&&
                                                                                              (attribute.Equals(wellKnownTypes.FactoryAttribute, SymbolEqualityComparer.Default) ||
                                                                                               attribute.Equals(wellKnownTypes.InstanceAttribute, SymbolEqualityComparer.Default) ||
                                                                                               attribute.Equals(wellKnownTypes.DecoratorFactoryAttribute, SymbolEqualityComparer.Default) ||
                                                                                               attribute.Equals(wellKnownTypes.FactoryOfAttribute, SymbolEqualityComparer.Default)))));

                foreach (var module in modules)
                {
                    if (!module.type.IsInternal() && !module.type.IsPublic())
                    {
                        reportDiagnostic(ModuleNotPublicOrInternal(
                                             module.type,
                                             ((TypeDeclarationSyntax)module.type.DeclaringSyntaxReferences[0].GetSyntax()).Identifier.GetLocation()));
                    }

                    cancellationToken.ThrowIfCancellationRequested();
                    if (module.isContainer)
                    {
                        var file = ContainerGenerator.GenerateContainerImplementations(
                            module.type,
                            registrationCalculator.GetContainerRegistrations(module.type),
                            wellKnownTypes,
                            reportDiagnostic,
                            cancellationToken);

                        var source = CSharpSyntaxTree.ParseText(SourceText.From(file, Encoding.UTF8)).GetRoot().NormalizeWhitespace().SyntaxTree.GetText();
                        context.AddSource(
                            GenerateNameHint(module.type),
                            source);
                    }
                    else
                    {
                        registrationCalculator.ValidateModuleRegistrations(module.type);
                    }
                }
            }
        }
示例#9
0
 public GrainReferenceGenerator(CodeGeneratorOptions options, WellKnownTypes wellKnownTypes)
 {
     this.options        = options;
     this.wellKnownTypes = wellKnownTypes;
 }
示例#10
0
        public sealed override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

            // Security analyzer - analyze and report diagnostics on generated code.
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                var compilation = compilationStartAnalysisContext.Compilation;
                var serializableAttributeTypeSymbol = WellKnownTypes.SerializableAttribute(compilation);

                if (serializableAttributeTypeSymbol == null)
                {
                    return;
                }

                var nonSerializedAttribute = WellKnownTypes.NonSerializedAttribute(compilation);

                if (nonSerializedAttribute == null)
                {
                    return;
                }

                var forwardGraph  = new ConcurrentDictionary <ISymbol, ConcurrentDictionary <ISymbol, bool> >();
                var invertedGraph = new ConcurrentDictionary <ISymbol, ConcurrentDictionary <ISymbol, bool> >();

                // It keeps the out Degree of every vertex in the invertedGraph, which is corresponding to the in Degree of the vertex in forwardGraph.
                var inDegree = new ConcurrentDictionary <ISymbol, int>();

                // It Keeps the out degree of every vertex in the forwardGraph, which is corresponding to the in Degree of the vertex in invertedGraph.
                var outDegree = new ConcurrentDictionary <ISymbol, int>();

                compilationStartAnalysisContext.RegisterSymbolAction(
                    (SymbolAnalysisContext symbolAnalysisContext) =>
                {
                    DrawGraph(symbolAnalysisContext.Symbol as ITypeSymbol);
                }, SymbolKind.NamedType);

                compilationStartAnalysisContext.RegisterCompilationEndAction(
                    (CompilationAnalysisContext compilationAnalysisContext) =>
                {
                    ModifyDegree(inDegree, forwardGraph);
                    ModifyDegree(outDegree, invertedGraph);

                    // If the degree of a vertex is greater than 0 both in the forward graph and inverted graph after topological sorting,
                    // the vertex must belong to a loop.
                    var leftVertices         = inDegree.Where(s => s.Value > 0).Select(s => s.Key).ToImmutableHashSet();
                    var invertedLeftVertices = outDegree.Where(s => s.Value > 0).Select(s => s.Key).ToImmutableHashSet();
                    var verticesInLoop       = leftVertices.Intersect(invertedLeftVertices);

                    foreach (var vertex in verticesInLoop)
                    {
                        if (vertex is IFieldSymbol fieldInLoop)
                        {
                            var associatedSymbol = fieldInLoop.AssociatedSymbol;
                            compilationAnalysisContext.ReportDiagnostic(
                                fieldInLoop.CreateDiagnostic(
                                    Rule,
                                    associatedSymbol == null ? vertex.Name : associatedSymbol.Name));
                        }
                    }
                });

                // Traverse from point to its descendants, save the information into a directed graph.
                //
                // point: The initial point
                void DrawGraph(ITypeSymbol point)
                {
                    // If the point has been visited, return;
                    // otherwise, add it to the graph and mark it as visited.
                    if (!AddPointToBothGraphs(point))
                    {
                        return;
                    }

                    foreach (var associatedTypePoint in GetAssociatedTypes(point))
                    {
                        if (associatedTypePoint == null ||
                            associatedTypePoint.Equals(point))
                        {
                            continue;
                        }

                        AddLineToBothGraphs(point, associatedTypePoint);
                        DrawGraph(associatedTypePoint);
                    }

                    if (point.IsInSource() &&
                        point.HasAttribute(serializableAttributeTypeSymbol))
                    {
                        var fieldPoints = point.GetMembers().OfType <IFieldSymbol>().Where(s => !s.HasAttribute(nonSerializedAttribute) &&
                                                                                           !s.IsStatic);

                        foreach (var fieldPoint in fieldPoints)
                        {
                            var fieldTypePoint = fieldPoint.Type;
                            AddLineToBothGraphs(point, fieldPoint);
                            AddLineToBothGraphs(fieldPoint, fieldTypePoint);
                            DrawGraph(fieldTypePoint);
                        }
                    }
                }

                static HashSet <ITypeSymbol> GetAssociatedTypes(ITypeSymbol type)
                {
                    var result = new HashSet <ITypeSymbol>();

                    if (type is INamedTypeSymbol namedTypeSymbol)
                    {
                        // 1. Type arguments of generic type.
                        if (namedTypeSymbol.IsGenericType)
                        {
                            foreach (var arg in namedTypeSymbol.TypeArguments)
                            {
                                result.Add(arg);
                            }
                        }

                        // 2. The type it constructed from.
                        var constructedFrom = namedTypeSymbol.ConstructedFrom;
                        result.Add(constructedFrom);
                    }
                    else if (type is IArrayTypeSymbol arrayTypeSymbol)
                    {
                        // 3. Element type of the array.
                        result.Add(arrayTypeSymbol.ElementType);
                    }

                    // 4. Base type.
                    result.Add(type.BaseType);

                    return(result);
                }

                // Add a line to the graph.
                //
                // from: The start point of the line
                // to: The end point of the line
                // degree: The out degree of all vertices in the graph
                // graph: The graph
                void AddLine(ISymbol from, ISymbol to, ConcurrentDictionary <ISymbol, int> degree, ConcurrentDictionary <ISymbol, ConcurrentDictionary <ISymbol, bool> > graph)
                {
                    graph.AddOrUpdate(from, new ConcurrentDictionary <ISymbol, bool> {
                        [to] = true
                    }, (k, v) => { v[to] = true; return(v); });
                    degree.AddOrUpdate(from, 1, (k, v) => v + 1);
                }
示例#11
0
        private static async Task <Document> AddSerializableAttribute(Document document, SyntaxNode node, CancellationToken cancellationToken)
        {
            DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            SyntaxNode attr = editor.Generator.Attribute(editor.Generator.TypeExpression(WellKnownTypes.SerializableAttribute(editor.SemanticModel.Compilation)));

            editor.AddAttribute(node, attr);
            return(editor.GetChangedDocument());
        }
        public override void Initialize(AnalysisContext analysisContext)
        {
            // TODO: Make analyzer thread safe
            //analysisContext.EnableConcurrentExecution();

            // We need to analyze generated code, but don't intend to report diagnostics for generated code fields.
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze);

            analysisContext.RegisterCompilationStartAction(
                (compilationContext) =>
            {
                HashSet <IFieldSymbol> unreferencedPrivateFields = new HashSet <IFieldSymbol>();
                HashSet <IFieldSymbol> referencedPrivateFields   = new HashSet <IFieldSymbol>();

                ImmutableHashSet <INamedTypeSymbol> specialAttributes = GetSpecialAttributes(compilationContext.Compilation);
                var structLayoutAttribute = WellKnownTypes.StructLayoutAttribute(compilationContext.Compilation);

                compilationContext.RegisterSymbolAction(
                    (symbolContext) =>
                {
                    IFieldSymbol field = (IFieldSymbol)symbolContext.Symbol;

                    // Fields of types marked with StructLayoutAttribute with LayoutKind.Sequential should never be flagged as unused as their removal can change the runtime behavior.
                    if (structLayoutAttribute != null && field.ContainingType != null)
                    {
                        foreach (var attribute in field.ContainingType.GetAttributes())
                        {
                            if (structLayoutAttribute.Equals(attribute.AttributeClass.OriginalDefinition) &&
                                attribute.ConstructorArguments.Length == 1)
                            {
                                var argument = attribute.ConstructorArguments[0];
                                if (argument.Type != null)
                                {
                                    SpecialType specialType = argument.Type.TypeKind == TypeKind.Enum ?
                                                              ((INamedTypeSymbol)argument.Type).EnumUnderlyingType.SpecialType :
                                                              argument.Type.SpecialType;

                                    if (DiagnosticHelpers.TryConvertToUInt64(argument.Value, specialType, out ulong convertedLayoutKindValue) &&
                                        convertedLayoutKindValue == (ulong)System.Runtime.InteropServices.LayoutKind.Sequential)
                                    {
                                        return;
                                    }
                                }
                            }
                        }
                    }

                    if (field.DeclaredAccessibility == Accessibility.Private && !referencedPrivateFields.Contains(field))
                    {
                        // Fields with certain special attributes should never be considered unused.
                        if (!specialAttributes.IsEmpty)
                        {
                            foreach (var attribute in field.GetAttributes())
                            {
                                if (specialAttributes.Contains(attribute.AttributeClass.OriginalDefinition))
                                {
                                    return;
                                }
                            }
                        }

                        unreferencedPrivateFields.Add(field);
                    }
                },
                    SymbolKind.Field);

                compilationContext.RegisterOperationAction(
                    (operationContext) =>
                {
                    IFieldSymbol field = ((IFieldReferenceOperation)operationContext.Operation).Field;
                    if (field.DeclaredAccessibility == Accessibility.Private)
                    {
                        referencedPrivateFields.Add(field);
                        unreferencedPrivateFields.Remove(field);
                    }
                },
                    OperationKind.FieldReference);

                compilationContext.RegisterCompilationEndAction(
                    (compilationEndContext) =>
                {
                    foreach (IFieldSymbol unreferencedPrivateField in unreferencedPrivateFields)
                    {
                        compilationEndContext.ReportDiagnostic(Diagnostic.Create(Rule, unreferencedPrivateField.Locations[0], unreferencedPrivateField.Name));
                    }
                });
            });
        }
示例#13
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationContext =>
            {
                INamedTypeSymbol localizableStateAttributeSymbol  = WellKnownTypes.LocalizableAttribute(compilationContext.Compilation);
                INamedTypeSymbol conditionalAttributeSymbol       = WellKnownTypes.ConditionalAttribute(compilationContext.Compilation);
                INamedTypeSymbol systemConsoleSymbol              = WellKnownTypes.Console(compilationContext.Compilation);
                ImmutableHashSet <INamedTypeSymbol> typesToIgnore = GetTypesToIgnore(compilationContext.Compilation);

                compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext =>
                {
                    if (!(operationBlockStartContext.OwningSymbol is IMethodSymbol containingMethod))
                    {
                        return;
                    }

                    var lazyValueContentResult = new Lazy <DataFlowAnalysisResult <ValueContentBlockAnalysisResult, ValueContentAbstractValue> >(
                        valueFactory: ComputeValueContentAnalysisResult, isThreadSafe: false);

                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        var argument = (IArgumentOperation)operationContext.Operation;
                        switch (argument.Parent?.Kind)
                        {
                        case OperationKind.Invocation:
                        case OperationKind.ObjectCreation:
                            AnalyzeArgument(argument.Parameter, containingPropertySymbolOpt: null, operation: argument, reportDiagnostic: operationContext.ReportDiagnostic);
                            return;
                        }
                    }, OperationKind.Argument);

                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        var propertyReference = (IPropertyReferenceOperation)operationContext.Operation;
                        if (propertyReference.Parent is IAssignmentOperation assignment &&
                            assignment.Target == propertyReference &&
                            !propertyReference.Property.IsIndexer &&
                            propertyReference.Property.SetMethod?.Parameters.Length == 1)
                        {
                            IParameterSymbol valueSetterParam = propertyReference.Property.SetMethod.Parameters[0];
                            AnalyzeArgument(valueSetterParam, propertyReference.Property, assignment, operationContext.ReportDiagnostic);
                        }
                    }, OperationKind.PropertyReference);

                    void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol containingPropertySymbolOpt, IOperation operation, Action <Diagnostic> reportDiagnostic)
                    {
                        if (ShouldBeLocalized(parameter, containingPropertySymbolOpt, localizableStateAttributeSymbol, conditionalAttributeSymbol, systemConsoleSymbol, typesToIgnore))
                        {
                            ValueContentAbstractValue stringContentValue = lazyValueContentResult.Value[operation.Kind, operation.Syntax];
                            if (stringContentValue.IsLiteralState)
                            {
                                Debug.Assert(stringContentValue.LiteralValues.Count > 0);

                                if (stringContentValue.LiteralValues.Any(l => !(l is string)))
                                {
                                    return;
                                }

                                var stringLiteralValues = stringContentValue.LiteralValues.Select(l => (string)l);

                                // FxCop compat: Do not fire if the literal value came from a default parameter value
                                if (stringContentValue.LiteralValues.Count == 1 &&
                                    parameter.IsOptional &&
                                    parameter.ExplicitDefaultValue is string defaultValue &&
                                    defaultValue == stringLiteralValues.Single())
                                {
                                    return;
                                }

                                // FxCop compat: Do not fire if none of the string literals have any non-control character.
                                if (!LiteralValuesHaveNonControlCharacters(stringLiteralValues))
                                {
                                    return;
                                }

                                // FxCop compat: Filter out xml string literals.
                                var filteredStrings = stringLiteralValues.Where(literal => !LooksLikeXmlTag(literal));
                                if (filteredStrings.Any())
                                {
                                    // Method '{0}' passes a literal string as parameter '{1}' of a call to '{2}'. Retrieve the following string(s) from a resource table instead: "{3}".
                                    var arg1       = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                                    var arg2       = parameter.Name;
                                    var arg3       = parameter.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                                    var arg4       = FormatLiteralValues(filteredStrings);
                                    var diagnostic = operation.CreateDiagnostic(Rule, arg1, arg2, arg3, arg4);
                                    reportDiagnostic(diagnostic);
                                }
                            }
                        }
                    }

                    DataFlowAnalysisResult <ValueContentBlockAnalysisResult, ValueContentAbstractValue> ComputeValueContentAnalysisResult()
                    {
                        foreach (var operationRoot in operationBlockStartContext.OperationBlocks)
                        {
                            IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock();
                            if (topmostBlock != null)
                            {
                                var cfg = topmostBlock.GetEnclosingControlFlowGraph();
                                var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(operationBlockStartContext.Compilation);
                                return(ValueContentAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider,
                                                                               operationBlockStartContext.Options, Rule, operationBlockStartContext.CancellationToken));
                            }
                        }

                        return(null);
                    }
                });
            });
        }
示例#14
0
        internal NamedTypeSymbol GetCallSiteDelegateType(
            TypeSymbol loweredReceiver,
            RefKind receiverRefKind,
            ImmutableArray <TypeSymbol> loweredArguments,
            ImmutableArray <RefKind> refKinds,
            TypeSymbol loweredRight,
            TypeSymbol resultType)
        {
            Debug.Assert(refKinds.IsDefaultOrEmpty || refKinds.Length == loweredArguments.Length);

            var callSiteType = this.CallSite;

            if (callSiteType.IsErrorType())
            {
                return(null);
            }

            var  delegateSignature = MakeCallSiteDelegateSignature(callSiteType, loweredReceiver, loweredArguments, loweredRight, resultType);
            bool returnsVoid       = resultType.SpecialType == SpecialType.System_Void;
            bool hasByRefs         = receiverRefKind != RefKind.None || !refKinds.IsDefaultOrEmpty;

            if (!hasByRefs)
            {
                var wkDelegateType = returnsVoid ?
                                     WellKnownTypes.GetWellKnownActionDelegate(invokeArgumentCount: delegateSignature.Length) :
                                     WellKnownTypes.GetWellKnownFunctionDelegate(invokeArgumentCount: delegateSignature.Length - 1);

                if (wkDelegateType != WellKnownType.Unknown)
                {
                    var delegateType = _compilation.GetWellKnownType(wkDelegateType);
                    if (delegateType != null && !delegateType.IsErrorType())
                    {
                        return(delegateType.Construct(delegateSignature));
                    }
                }
            }

            BitVector byRefs;

            if (hasByRefs)
            {
                byRefs = BitVector.Create(1 + (loweredReceiver != null ? 1 : 0) + loweredArguments.Length + (loweredRight != null ? 1 : 0));

                int j = 1;
                if (loweredReceiver != null)
                {
                    byRefs[j++] = receiverRefKind != RefKind.None;
                }

                if (!refKinds.IsDefault)
                {
                    for (int i = 0; i < refKinds.Length; i++, j++)
                    {
                        if (refKinds[i] != RefKind.None)
                        {
                            byRefs[j] = true;
                        }
                    }
                }
            }
            else
            {
                byRefs = default(BitVector);
            }

            int parameterCount = delegateSignature.Length - (returnsVoid ? 0 : 1);

            return(_compilation.AnonymousTypeManager.SynthesizeDelegate(parameterCount, byRefs, returnsVoid).Construct(delegateSignature));
        }
示例#15
0
        /// <summary>
        /// Returns syntax for the deserializer method.
        /// </summary>
        private static MemberDeclarationSyntax GenerateDeserializerMethod(WellKnownTypes wellKnownTypes, INamedTypeSymbol type, List <FieldInfoMember> fields, SemanticModel model)
        {
            var contextParameter = IdentifierName("context");

            var resultDeclaration =
                LocalDeclarationStatement(
                    VariableDeclaration(type.ToTypeSyntax())
                    .AddVariables(
                        VariableDeclarator("result")
                        .WithInitializer(EqualsValueClause(GetObjectCreationExpressionSyntax(wellKnownTypes, type, model)))));
            var resultVariable = IdentifierName("result");

            var body = new List <StatementSyntax> {
                resultDeclaration
            };

            // Value types cannot be referenced, only copied, so there is no need to box & record instances of value types.
            if (!type.IsValueType)
            {
                // Record the result for cyclic deserialization.
                var currentSerializationContext = contextParameter;
                body.Add(
                    ExpressionStatement(
                        InvocationExpression(currentSerializationContext.Member("RecordObject"))
                        .AddArgumentListArguments(Argument(resultVariable))));
            }

            // Deserialize all fields.
            foreach (var field in fields)
            {
                var deserialized =
                    InvocationExpression(contextParameter.Member("DeserializeInner"))
                    .AddArgumentListArguments(
                        Argument(TypeOfExpression(field.Type)));
                body.Add(
                    ExpressionStatement(
                        field.GetSetter(
                            resultVariable,
                            CastExpression(field.Type, deserialized))));
            }

            // If the type implements the internal IOnDeserialized lifecycle method, invoke it's method now.
            if (type.HasInterface(wellKnownTypes.IOnDeserialized))
            {
                // C#: ((IOnDeserialized)result).OnDeserialized(context);
                var typedResult          = ParenthesizedExpression(CastExpression(wellKnownTypes.IOnDeserialized.ToTypeSyntax(), resultVariable));
                var invokeOnDeserialized = InvocationExpression(typedResult.Member("OnDeserialized"))
                                           .AddArgumentListArguments(Argument(contextParameter));
                body.Add(ExpressionStatement(invokeOnDeserialized));
            }

            body.Add(ReturnStatement(CastExpression(type.ToTypeSyntax(), resultVariable)));
            return
                (MethodDeclaration(wellKnownTypes.Object.ToTypeSyntax(), "Deserializer")
                 .AddModifiers(Token(SyntaxKind.PublicKeyword))
                 .AddParameterListParameters(
                     Parameter(Identifier("expected")).WithType(wellKnownTypes.Type.ToTypeSyntax()),
                     Parameter(Identifier("context")).WithType(wellKnownTypes.IDeserializationContext.ToTypeSyntax()))
                 .AddBodyStatements(body.ToArray())
                 .AddAttributeLists(
                     AttributeList()
                     .AddAttributes(Attribute(wellKnownTypes.DeserializerMethodAttribute.ToNameSyntax()))));
        }
示例#16
0
        public CoreTypes(PhpCompilation compilation)
        {
            Contract.ThrowIfNull(compilation);
            _compilation = compilation;
            _table       = new Dictionary <string, CoreType>();

            Void                = Create(SpecialType.System_Void);
            Object              = Create(SpecialType.System_Object);
            Int32               = Create(SpecialType.System_Int32);
            Long                = Create(SpecialType.System_Int64);
            Double              = Create(SpecialType.System_Double);
            Boolean             = Create(SpecialType.System_Boolean);
            String              = Create(SpecialType.System_String);
            Exception           = CreateFromFullName(WellKnownTypes.GetMetadataName(WellKnownType.System_Exception));
            RuntimeTypeHandle   = Create(SpecialType.System_RuntimeTypeHandle);
            RuntimeMethodHandle = Create(SpecialType.System_RuntimeMethodHandle);

            PhpNumber                    = Create("PhpNumber");
            PhpAlias                     = Create("PhpAlias");
            PhpValue                     = Create("PhpValue");
            PhpString                    = Create("PhpString");
            PhpArray                     = Create("PhpArray");
            PhpResource                  = Create("PhpResource");
            IPhpArray                    = Create("IPhpArray");
            IPhpEnumerable               = Create("IPhpEnumerable");
            IPhpCallable                 = Create("IPhpCallable");
            IPhpConvertible              = Create("IPhpConvertible");
            PhpString_Blob               = Create("PhpString+Blob");
            IntStringKey                 = Create("IntStringKey");
            PhpHashtable                 = Create("PhpHashtable");
            ScriptDiedException          = Create("ScriptDiedException");
            Context                      = Create("Context");
            Operators                    = Create("Operators");
            Comparison                   = Create("Comparison");
            StrictComparison             = Create("StrictComparison");
            Convert                      = Create("Convert");
            PhpException                 = Create("PhpException");
            ScriptAttribute              = Create("ScriptAttribute");
            PhpTraitAttribute            = Create(PhpTraitAttributeName);
            PhpTypeAttribute             = Create("PhpTypeAttribute");
            PhpHiddenAttribute           = Create("PhpHiddenAttribute");
            PhpFieldsOnlyCtorAttribute   = Create(PhpFieldsOnlyCtorAttributeName);
            NotNullAttribute             = Create("NotNullAttribute");
            PhpMemberVisibilityAttribute = Create(PhpMemberVisibilityAttributeName);
            IStaticInit                  = Create("IStaticInit");
            RoutineInfo                  = Create("Reflection.RoutineInfo");
            stdClass                     = CreateFromFullName("stdClass");
            ArrayAccess                  = CreateFromFullName("ArrayAccess");
            Closure                      = CreateFromFullName("Closure");

            BinderFactory       = Create("Dynamic.BinderFactory");
            GetClassConstBinder = Create("Dynamic.GetClassConstBinder");
            GetFieldBinder      = Create("Dynamic.GetFieldBinder");
            SetFieldBinder      = Create("Dynamic.SetFieldBinder");
            AccessMask          = CreateFromFullName("Pchp.CodeAnalysis.Semantics.AccessMask");

            Dynamic_NameParam_T      = Create("Dynamic.NameParam`1");
            Dynamic_TargetTypeParam  = Create("Dynamic.TargetTypeParam");
            Dynamic_CallerTypeParam  = Create("Dynamic.CallerTypeParam");
            Dynamic_UnpackingParam_T = Create("Dynamic.UnpackingParam`1");

            PhpTypeInfoExtension = Create("Reflection.PhpTypeInfoExtension");
            PhpTypeInfo          = Create("Reflection.PhpTypeInfo");
            CommonPhpArrayKeys   = Create("CommonPhpArrayKeys");

            Iterator  = CreateFromFullName("Iterator");
            Generator = CreateFromFullName("Generator");
            GeneratorStateMachineDelegate = CreateFromFullName("GeneratorStateMachineDelegate");

            IntPtr = CreateFromFullName("System.IntPtr");
        }
示例#17
0
        /// <summary>
        /// Returns a sorted list of the fields of the provided type.
        /// </summary>
        private static List <FieldInfoMember> GetFields(WellKnownTypes wellKnownTypes, SemanticModel model, INamedTypeSymbol type, ILogger logger)
        {
            var result = new List <FieldInfoMember>();

            foreach (var field in type.GetDeclaredMembers <IFieldSymbol>())
            {
                if (ShouldSerializeField(wellKnownTypes, field))
                {
                    result.Add(new FieldInfoMember(wellKnownTypes, model, type, field, result.Count));
                }
            }

            if (type.TypeKind == TypeKind.Class)
            {
                // Some reference assemblies are compiled without private fields.
                // Warn the user if they are inheriting from a type in one of these assemblies using a heuristic:
                // If the type inherits from a type in a reference assembly and there are no fields declared on those
                // base types, emit a warning.
                var hasUnsupportedRefAsmBase   = false;
                var referenceAssemblyHasFields = false;
                var baseType = type.BaseType;
                while (baseType != null &&
                       !baseType.Equals(wellKnownTypes.Object) &&
                       !baseType.Equals(wellKnownTypes.Attribute))
                {
                    if (!hasUnsupportedRefAsmBase &&
                        baseType.ContainingAssembly.HasAttribute("ReferenceAssemblyAttribute") &&
                        !IsSupportedRefAsmType(baseType))
                    {
                        hasUnsupportedRefAsmBase = true;
                    }
                    foreach (var field in baseType.GetDeclaredMembers <IFieldSymbol>())
                    {
                        if (hasUnsupportedRefAsmBase)
                        {
                            referenceAssemblyHasFields = true;
                        }
                        if (ShouldSerializeField(wellKnownTypes, field))
                        {
                            result.Add(new FieldInfoMember(wellKnownTypes, model, type, field, result.Count));
                        }
                    }

                    baseType = baseType.BaseType;
                }

                if (hasUnsupportedRefAsmBase && !referenceAssemblyHasFields)
                {
                    var fileLocation = string.Empty;
                    var declaration  = type.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() as ClassDeclarationSyntax;
                    if (declaration != null)
                    {
                        var location = declaration.Identifier.GetLocation();
                        if (location.IsInSource)
                        {
                            var pos = location.GetLineSpan();
                            fileLocation = string.Format(
                                "{0}({1},{2},{3},{4}): ",
                                pos.Path,
                                pos.StartLinePosition.Line + 1,
                                pos.StartLinePosition.Character + 1,
                                pos.EndLinePosition.Line + 1,
                                pos.EndLinePosition.Character + 1);
                        }
                    }

                    logger.LogWarning(
                        $"{fileLocation}warning ORL1001: Type {type} has a base type which belongs to a reference assembly."
                        + " Serializer generation for this type may not include important base type fields.");
                }

                bool IsSupportedRefAsmType(INamedTypeSymbol t)
                {
                    INamedTypeSymbol baseDefinition;

                    if (t.IsGenericType && !t.IsUnboundGenericType)
                    {
                        baseDefinition = t.ConstructUnboundGenericType().OriginalDefinition;
                    }
                    else
                    {
                        baseDefinition = t.OriginalDefinition;
                    }

                    foreach (var refAsmType in wellKnownTypes.SupportedRefAsmBaseTypes)
                    {
                        if (baseDefinition.Equals(refAsmType))
                        {
                            return(true);
                        }
                    }

                    return(false);
                }
            }

            result.Sort(FieldInfoMember.Comparer.Instance);
            return(result);
        }
示例#18
0
        public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.EnableConcurrentExecution();
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            analysisContext.RegisterCompilationStartAction(
                compilationStartAnalysisContext =>
            {
                Compilation compilation = compilationStartAnalysisContext.Compilation;

                ImmutableHashSet <INamedTypeSymbol> nativeResourceTypes = ImmutableHashSet.Create(
                    WellKnownTypes.IntPtr(compilation),
                    WellKnownTypes.UIntPtr(compilation),
                    WellKnownTypes.HandleRef(compilation)
                    );
                var disposableType = WellKnownTypes.IDisposable(compilation);

                compilationStartAnalysisContext.RegisterOperationAction(
                    operationAnalysisContext =>
                {
                    var assignment = (IAssignmentOperation)operationAnalysisContext.Operation;

                    IOperation target = assignment.Target;
                    if (target == null)
                    {
                        // This can happen if the left-hand side is an undefined symbol.
                        return;
                    }

                    if (target.Kind != OperationKind.FieldReference)
                    {
                        return;
                    }

                    var fieldReference = (IFieldReferenceOperation)target;
                    var field          = fieldReference.Member as IFieldSymbol;
                    if (field == null || field.Kind != SymbolKind.Field || field.IsStatic)
                    {
                        return;
                    }

                    if (!nativeResourceTypes.Contains(field.Type))
                    {
                        return;
                    }

                    INamedTypeSymbol containingType = field.ContainingType;
                    if (containingType == null || containingType.IsValueType)
                    {
                        return;
                    }

                    if (!containingType.AllInterfaces.Contains(disposableType))
                    {
                        return;
                    }

                    if (containingType.HasFinalizer())
                    {
                        return;
                    }

                    if (assignment.Value == null || assignment.Value.Kind != OperationKind.Invocation)
                    {
                        return;
                    }

                    var invocation = (IInvocationOperation)assignment.Value;
                    if (invocation == null)
                    {
                        return;
                    }

                    IMethodSymbol method = invocation.TargetMethod;

                    // TODO: What about COM?
                    if (method.GetDllImportData() == null)
                    {
                        return;
                    }

                    operationAnalysisContext.ReportDiagnostic(containingType.CreateDiagnostic(Rule));
                },
                    OperationKind.SimpleAssignment);
            });
        }
示例#19
0
        internal static bool IsOrleansShallowCopyable(WellKnownTypes wellKnownTypes, ITypeSymbol type, HashSet <ITypeSymbol> examining)
        {
            switch (type.SpecialType)
            {
            case SpecialType.System_Boolean:
            case SpecialType.System_Char:
            case SpecialType.System_SByte:
            case SpecialType.System_Byte:
            case SpecialType.System_Int16:
            case SpecialType.System_UInt16:
            case SpecialType.System_Int32:
            case SpecialType.System_UInt32:
            case SpecialType.System_Int64:
            case SpecialType.System_UInt64:
            case SpecialType.System_Decimal:
            case SpecialType.System_Single:
            case SpecialType.System_Double:
            case SpecialType.System_String:
            case SpecialType.System_DateTime:
                return(true);
            }

            if (wellKnownTypes.TimeSpan.Equals(type) ||
                wellKnownTypes.IPAddress.Equals(type) ||
                wellKnownTypes.IPEndPoint.Equals(type) ||
                wellKnownTypes.SiloAddress.Equals(type) ||
                wellKnownTypes.GrainId.Equals(type) ||
                wellKnownTypes.ActivationId.Equals(type) ||
                wellKnownTypes.ActivationAddress.Equals(type) ||
                wellKnownTypes.CorrelationId is WellKnownTypes.Some correlationIdType && correlationIdType.Value.Equals(type) ||
                wellKnownTypes.CancellationToken.Equals(type))
            {
                return(true);
            }

            if (ShallowCopyableTypes.TryGetValue(type, out var result))
            {
                return(result);
            }

            if (type.HasAttribute(wellKnownTypes.ImmutableAttribute))
            {
                return(ShallowCopyableTypes[type] = true);
            }

            if (type.HasBaseType(wellKnownTypes.Exception))
            {
                return(ShallowCopyableTypes[type] = true);
            }

            if (!(type is INamedTypeSymbol namedType))
            {
                return(ShallowCopyableTypes[type] = false);
            }

            if (namedType.IsGenericType && wellKnownTypes.Immutable_1.Equals(namedType.ConstructedFrom))
            {
                return(ShallowCopyableTypes[type] = true);
            }

            if (type.TypeKind == TypeKind.Struct && !namedType.IsGenericType && !namedType.IsUnboundGenericType)
            {
                return(ShallowCopyableTypes[type] = IsValueTypeFieldsShallowCopyable(wellKnownTypes, type, examining));
            }

            return(ShallowCopyableTypes[type] = false);
        }
        /// <summary>
        /// Check whether given symbol is from mscorlib
        /// </summary>
        public static bool IsFromMscorlib(this ISymbol symbol, Compilation compilation)
        {
            var @object = WellKnownTypes.Object(compilation);

            return(symbol.ContainingAssembly?.Equals(@object.ContainingAssembly) == true);
        }
示例#21
0
        private static List <MethodCategory> GetMethodCategories(Compilation compilation)
        {
            var methodCategories = new List <MethodCategory> {
                new MethodCategory(IsPropertyGetter, true,
                                   PropertyGetterRule,
                                   WellKnownTypes.InvalidOperationException(compilation), WellKnownTypes.NotSupportedException(compilation)),

                new MethodCategory(IsIndexerGetter, true,
                                   PropertyGetterRule,
                                   WellKnownTypes.InvalidOperationException(compilation), WellKnownTypes.NotSupportedException(compilation),
                                   WellKnownTypes.ArgumentException(compilation), WellKnownTypes.KeyNotFoundException(compilation)),

                new MethodCategory(IsEventAccessor, true,
                                   HasAllowedExceptionsRule,
                                   WellKnownTypes.InvalidOperationException(compilation), WellKnownTypes.NotSupportedException(compilation),
                                   WellKnownTypes.ArgumentException(compilation)),

                new MethodCategory(IsGetHashCodeInterfaceImplementation, true,
                                   HasAllowedExceptionsRule,
                                   WellKnownTypes.ArgumentException(compilation)),

                new MethodCategory(IsEqualsOverrideOrInterfaceImplementation, true,
                                   NoAllowedExceptionsRule),

                new MethodCategory(IsEqualityOperator, true,
                                   NoAllowedExceptionsRule),

                new MethodCategory(IsGetHashCodeOverride, true,
                                   NoAllowedExceptionsRule),

                new MethodCategory(IsToString, true,
                                   NoAllowedExceptionsRule),

                new MethodCategory(IsImplicitCastOperator, true,
                                   NoAllowedExceptionsRule),

                new MethodCategory(IsStaticConstructor, false,
                                   NoAllowedExceptionsRule),

                new MethodCategory(IsFinalizer, false,
                                   NoAllowedExceptionsRule),

                new MethodCategory(IMethodSymbolExtensions.IsDisposeImplementation, true,
                                   NoAllowedExceptionsRule),
            };

            return(methodCategories);
        }
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.RegisterCompilationStartAction(compilationContext =>
            {
                INamedTypeSymbol iDbCommandType     = WellKnownTypes.IDbCommand(compilationContext.Compilation);
                INamedTypeSymbol iDataAdapterType   = WellKnownTypes.IDataAdapter(compilationContext.Compilation);
                IPropertySymbol commandTextProperty = iDbCommandType?.GetMembers("CommandText").OfType <IPropertySymbol>().FirstOrDefault();

                if (iDbCommandType == null ||
                    iDataAdapterType == null ||
                    commandTextProperty == null)
                {
                    return;
                }

                compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext =>
                {
                    ISymbol symbol = operationBlockStartContext.OwningSymbol;
                    if (symbol.IsConfiguredToSkipAnalysis(operationBlockStartContext.Options,
                                                          Rule, operationBlockStartContext.Compilation, operationBlockStartContext.CancellationToken))
                    {
                        return;
                    }

                    var isInDbCommandConstructor   = false;
                    var isInDataAdapterConstructor = false;

                    if (symbol.Kind != SymbolKind.Method)
                    {
                        return;
                    }

                    var methodSymbol = (IMethodSymbol)symbol;

                    if (methodSymbol.MethodKind == MethodKind.Constructor)
                    {
                        CheckForDbCommandAndDataAdapterImplementation(symbol.ContainingType, iDbCommandType, iDataAdapterType, out isInDbCommandConstructor, out isInDataAdapterConstructor);
                    }

                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        var creation = (IObjectCreationOperation)operationContext.Operation;
                        AnalyzeMethodCall(operationContext, creation.Constructor, symbol, creation.Arguments, creation.Syntax, isInDbCommandConstructor, isInDataAdapterConstructor, iDbCommandType, iDataAdapterType);
                    }, OperationKind.ObjectCreation);

                    // If an object calls a constructor in a base class or the same class, this will get called.
                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        var invocation = (IInvocationOperation)operationContext.Operation;

                        // We only analyze constructor invocations
                        if (invocation.TargetMethod.MethodKind != MethodKind.Constructor)
                        {
                            return;
                        }

                        // If we're calling another constructor in the same class from this constructor, assume that all parameters are safe and skip analysis. Parameter usage
                        // will be analyzed there
                        if (Equals(invocation.TargetMethod.ContainingType, symbol.ContainingType))
                        {
                            return;
                        }

                        AnalyzeMethodCall(operationContext, invocation.TargetMethod, symbol, invocation.Arguments, invocation.Syntax, isInDbCommandConstructor, isInDataAdapterConstructor, iDbCommandType, iDataAdapterType);
                    }, OperationKind.Invocation);

                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        var propertyReference = (IPropertyReferenceOperation)operationContext.Operation;

                        // We're only interested in implementations of IDbCommand.CommandText
                        if (!propertyReference.Property.IsOverrideOrImplementationOfInterfaceMember(commandTextProperty))
                        {
                            return;
                        }

                        // Make sure we're in assignment statement
                        if (!(propertyReference.Parent is IAssignmentOperation assignment))
                        {
                            return;
                        }

                        // Only if the property reference is actually the target of the assignment
                        if (assignment.Target != propertyReference)
                        {
                            return;
                        }

                        ReportDiagnosticIfNecessary(operationContext, assignment.Value, assignment.Syntax, propertyReference.Property, symbol);
                    }, OperationKind.PropertyReference);
                });
            });
        }
示例#23
0
        private static void AssertNoIsByRefLikeAttributeExists(AssemblySymbol assembly)
        {
            var isByRefLikeAttributeTypeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute);

            Assert.Null(assembly.GetTypeByMetadataName(isByRefLikeAttributeTypeName));
        }
示例#24
0
        private async Task <Document> GenerateConstructor(Document document, SyntaxNode node, ISymbol symbol, INamedTypeSymbol notImplementedExceptionType, CancellationToken cancellationToken)
        {
            SymbolEditor editor     = SymbolEditor.Create(document);
            var          typeSymbol = symbol as INamedTypeSymbol;

            await editor.EditOneDeclarationAsync(typeSymbol, node.GetLocation(), (docEditor, declaration) =>
            {
                SyntaxGenerator generator = docEditor.Generator;
                SyntaxNode throwStatement = generator.ThrowStatement(generator.ObjectCreationExpression(generator.TypeExpression(notImplementedExceptionType)));
                SyntaxNode ctorDecl       = generator.ConstructorDeclaration(
                    typeSymbol.Name,
                    new[]
                {
                    generator.ParameterDeclaration("serializationInfo", generator.TypeExpression(WellKnownTypes.SerializationInfo(docEditor.SemanticModel.Compilation))),
                    generator.ParameterDeclaration("streamingContext", generator.TypeExpression(WellKnownTypes.StreamingContext(docEditor.SemanticModel.Compilation)))
                },
                    typeSymbol.IsSealed ? Accessibility.Private : Accessibility.Protected,
                    statements: new[] { throwStatement });

                docEditor.AddMember(declaration, ctorDecl);
            }, cancellationToken).ConfigureAwait(false);

            return(editor.GetChangedDocuments().First());
        }
示例#25
0
        internal NamedTypeSymbol GetDelegateType(
            BoundExpression loweredReceiver,
            RefKind receiverRefKind,
            ImmutableArray <BoundExpression> loweredArguments,
            ImmutableArray <RefKind> refKinds,
            BoundExpression loweredRight,
            TypeSymbol resultType)
        {
            Debug.Assert(refKinds.IsDefaultOrEmpty || refKinds.Length == loweredArguments.Length);

            var callSiteType = _factory.WellKnownType(WellKnownType.System_Runtime_CompilerServices_CallSite);

            if (callSiteType.IsErrorType())
            {
                return(null);
            }

            var  delegateSignature = MakeCallSiteDelegateSignature(callSiteType, loweredReceiver, loweredArguments, loweredRight, resultType);
            bool returnsVoid       = resultType.SpecialType == SpecialType.System_Void;
            bool hasByRefs         = receiverRefKind != RefKind.None || !refKinds.IsDefaultOrEmpty;

            if (!hasByRefs)
            {
                var wkDelegateType = returnsVoid ?
                                     WellKnownTypes.GetWellKnownActionDelegate(invokeArgumentCount: delegateSignature.Length) :
                                     WellKnownTypes.GetWellKnownFunctionDelegate(invokeArgumentCount: delegateSignature.Length - 1);

                if (wkDelegateType != WellKnownType.Unknown)
                {
                    var delegateType = _factory.Compilation.GetWellKnownType(wkDelegateType);
                    if (!delegateType.HasUseSiteError)
                    {
                        return(delegateType.Construct(delegateSignature));
                    }
                }
            }

            BitVector byRefs;

            if (hasByRefs)
            {
                byRefs = BitVector.Create(1 + (loweredReceiver != null ? 1 : 0) + loweredArguments.Length + (loweredRight != null ? 1 : 0));

                int j = 1;
                if (loweredReceiver != null)
                {
                    byRefs[j++] = receiverRefKind != RefKind.None;
                }

                if (!refKinds.IsDefault)
                {
                    for (int i = 0; i < refKinds.Length; i++, j++)
                    {
                        if (refKinds[i] != RefKind.None)
                        {
                            byRefs[j] = true;
                        }
                    }
                }
            }
            else
            {
                byRefs = default(BitVector);
            }

            int parameterCount  = delegateSignature.Length - (returnsVoid ? 0 : 1);
            int generation      = _factory.CompilationState.ModuleBuilderOpt.CurrentGenerationOrdinal;
            var synthesizedType = _factory.Compilation.AnonymousTypeManager.SynthesizeDelegate(parameterCount, byRefs, returnsVoid, generation);

            return(synthesizedType.Construct(delegateSignature));
        }
示例#26
0
        /// <summary>
        /// Checks if the given method implements IDisposable.Dispose()
        /// </summary>
        public static bool IsDisposeImplementation(this IMethodSymbol method, Compilation compilation)
        {
            INamedTypeSymbol iDisposable = WellKnownTypes.IDisposable(compilation);

            return(method.IsDisposeImplementation(iDisposable));
        }
示例#27
0
        private static async Task <Document> AddConstructorsAsync(Document document, IEnumerable <Diagnostic> diagnostics, SyntaxNode root, CancellationToken cancellationToken)
        {
            DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            SyntaxGenerator generator = editor.Generator;
            SemanticModel   model     = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            CodeAnalysis.Text.TextSpan diagnosticSpan = diagnostics.First().Location.SourceSpan; // All the diagnostics are reported at the same location -- the name of the declared class -- so it doesn't matter which one we pick
            SyntaxNode node       = root.FindNode(diagnosticSpan);
            SyntaxNode targetNode = editor.Generator.GetDeclaration(node, DeclarationKind.Class);
            var        typeSymbol = model.GetDeclaredSymbol(targetNode) as INamedTypeSymbol;

            foreach (Diagnostic diagnostic in diagnostics)
            {
                var missingCtorSignature = (ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature)Enum.Parse(typeof(ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature), diagnostic.Properties["Signature"]);

                switch (missingCtorSignature)
                {
                case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithNoParameter:
                    // Add missing CtorWithNoParameter
                    SyntaxNode newConstructorNode1 = generator.ConstructorDeclaration(typeSymbol.Name, accessibility: Accessibility.Public);
                    editor.AddMember(targetNode, newConstructorNode1);
                    break;

                case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithStringParameter:
                    // Add missing CtorWithStringParameter
                    SyntaxNode newConstructorNode2 = generator.ConstructorDeclaration(
                        containingTypeName: typeSymbol.Name,
                        parameters: new[]
                    {
                        generator.ParameterDeclaration("message", generator.TypeExpression(WellKnownTypes.String(editor.SemanticModel.Compilation)))
                    },
                        accessibility: Accessibility.Public,
                        baseConstructorArguments: new[]
                    {
                        generator.Argument(generator.IdentifierName("message"))
                    });
                    editor.AddMember(targetNode, newConstructorNode2);
                    break;

                case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithStringAndExceptionParameters:
                    // Add missing CtorWithStringAndExceptionParameters
                    SyntaxNode newConstructorNode3 = generator.ConstructorDeclaration(
                        containingTypeName: typeSymbol.Name,
                        parameters: new[]
                    {
                        generator.ParameterDeclaration("message", generator.TypeExpression(WellKnownTypes.String(editor.SemanticModel.Compilation))),
                        generator.ParameterDeclaration("innerException", generator.TypeExpression(WellKnownTypes.Exception(editor.SemanticModel.Compilation)))
                    },
                        accessibility: Accessibility.Public,
                        baseConstructorArguments: new[]
                    {
                        generator.Argument(generator.IdentifierName("message")),
                        generator.Argument(generator.IdentifierName("innerException"))
                    });
                    editor.AddMember(targetNode, newConstructorNode3);
                    break;
                }
            }

            return(editor.GetChangedDocument());
        }
示例#28
0
        private static MemberDeclarationSyntax GenerateConstructor(WellKnownTypes wellKnownTypes, string className, List <FieldInfoMember> fields)
        {
            var body = new List <StatementSyntax>();

            // Expressions for specifying binding flags.
            var bindingFlags = SymbolSyntaxExtensions.GetBindingFlagsParenthesizedExpressionSyntax(
                SyntaxKind.BitwiseOrExpression,
                BindingFlags.Instance,
                BindingFlags.NonPublic,
                BindingFlags.Public);

            var fieldUtils = IdentifierName("fieldUtils");

            foreach (var field in fields)
            {
                // Get the field
                var fieldInfoField = IdentifierName(field.InfoFieldName);
                var fieldInfo      =
                    InvocationExpression(TypeOfExpression(field.Field.ContainingType.ToTypeSyntax()).Member("GetField"))
                    .AddArgumentListArguments(
                        Argument(field.Field.Name.ToLiteralExpression()),
                        Argument(bindingFlags));
                var fieldInfoVariable =
                    VariableDeclarator(field.InfoFieldName).WithInitializer(EqualsValueClause(fieldInfo));

                if (!field.IsGettableProperty || !field.IsSettableProperty)
                {
                    body.Add(LocalDeclarationStatement(
                                 VariableDeclaration(wellKnownTypes.FieldInfo.ToTypeSyntax()).AddVariables(fieldInfoVariable)));
                }

                // Set the getter/setter of the field
                if (!field.IsGettableProperty)
                {
                    var getterType = wellKnownTypes.Func_2.Construct(field.Field.ContainingType, field.SafeType).ToTypeSyntax();

                    var getterInvoke = CastExpression(
                        getterType,
                        InvocationExpression(fieldUtils.Member("GetGetter")).AddArgumentListArguments(Argument(fieldInfoField)));

                    body.Add(ExpressionStatement(
                                 AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(field.GetterFieldName), getterInvoke)));
                }

                if (!field.IsSettableProperty)
                {
                    if (field.Field.ContainingType != null && field.Field.ContainingType.IsValueType)
                    {
                        var setterType = wellKnownTypes.ValueTypeSetter_2.Construct(field.Field.ContainingType, field.SafeType).ToTypeSyntax();

                        var getValueSetterInvoke = CastExpression(
                            setterType,
                            InvocationExpression(fieldUtils.Member("GetValueSetter"))
                            .AddArgumentListArguments(Argument(fieldInfoField)));

                        body.Add(ExpressionStatement(
                                     AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(field.SetterFieldName), getValueSetterInvoke)));
                    }
                    else
                    {
                        var setterType = wellKnownTypes.Action_2.Construct(field.Field.ContainingType, field.SafeType).ToTypeSyntax();

                        var getReferenceSetterInvoke = CastExpression(
                            setterType,
                            InvocationExpression(fieldUtils.Member("GetReferenceSetter"))
                            .AddArgumentListArguments(Argument(fieldInfoField)));

                        body.Add(ExpressionStatement(
                                     AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(field.SetterFieldName), getReferenceSetterInvoke)));
                    }
                }
            }

            return
                (ConstructorDeclaration(className)
                 .AddModifiers(Token(SyntaxKind.PublicKeyword))
                 .AddParameterListParameters(
                     Parameter(fieldUtils.Identifier).WithType(wellKnownTypes.IFieldUtils.ToTypeSyntax()))
                 .AddBodyStatements(body.ToArray()));
        }
示例#29
0
#pragma warning disable RS1026 // Enable concurrent execution
        public override void Initialize(AnalysisContext context)
#pragma warning restore RS1026 // Enable concurrent execution
        {
            // TODO: Consider making this analyzer thread-safe.
            //context.EnableConcurrentExecution();

            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationStartContext =>
            {
                INamedTypeSymbol eventsArgSymbol = compilationStartContext.Compilation.GetTypeByMetadataName("System.EventArgs");

                // Ignore conditional methods (FxCop compat - One conditional will often call another conditional method as its only use of a parameter)
                INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationStartContext.Compilation);

                // Ignore methods with special serialization attributes (FxCop compat - All serialization methods need to take 'StreamingContext')
                INamedTypeSymbol onDeserializingAttribute = WellKnownTypes.OnDeserializingAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onDeserializedAttribute  = WellKnownTypes.OnDeserializedAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onSerializingAttribute   = WellKnownTypes.OnSerializingAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onSerializedAttribute    = WellKnownTypes.OnSerializedAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol obsoleteAttribute        = WellKnownTypes.ObsoleteAttribute(compilationStartContext.Compilation);

                ImmutableHashSet <INamedTypeSymbol> attributeSetForMethodsToIgnore = ImmutableHashSet.Create(
                    conditionalAttributeSymbol,
                    onDeserializedAttribute,
                    onDeserializingAttribute,
                    onSerializedAttribute,
                    onSerializingAttribute,
                    obsoleteAttribute);

                UnusedParameterDictionary unusedMethodParameters = new ConcurrentDictionary <IMethodSymbol, ISet <IParameterSymbol> >();
                ISet <IMethodSymbol> methodsUsedAsDelegates      = new HashSet <IMethodSymbol>();

                // Create a list of functions to exclude from analysis. We assume that any function that is used in an IMethodBindingExpression
                // cannot have its signature changed, and add it to the list of methods to be excluded from analysis.
                compilationStartContext.RegisterOperationAction(operationContext =>
                {
                    var methodBinding = (IMethodReferenceOperation)operationContext.Operation;
                    methodsUsedAsDelegates.Add(methodBinding.Method.OriginalDefinition);
                }, OperationKind.MethodReference);

                compilationStartContext.RegisterOperationBlockStartAction(startOperationBlockContext =>
                {
                    // We only care about methods.
                    if (!(startOperationBlockContext.OwningSymbol is IMethodSymbol method))
                    {
                        return;
                    }

                    AnalyzeMethod(method, startOperationBlockContext, unusedMethodParameters,
                                  eventsArgSymbol, methodsUsedAsDelegates, attributeSetForMethodsToIgnore);

                    foreach (var localFunctionOperation in startOperationBlockContext.OperationBlocks.SelectMany(o => o.Descendants()).OfType <ILocalFunctionOperation>())
                    {
                        AnalyzeMethod(localFunctionOperation.Symbol, startOperationBlockContext, unusedMethodParameters,
                                      eventsArgSymbol, methodsUsedAsDelegates, attributeSetForMethodsToIgnore);
                    }
                });

                // Register a compilation end action to filter all methods used as delegates and report any diagnostics
                compilationStartContext.RegisterCompilationEndAction(compilationAnalysisContext =>
                {
                    // Report diagnostics for unused parameters.
                    var unusedParameters = unusedMethodParameters.Where(kvp => !methodsUsedAsDelegates.Contains(kvp.Key)).SelectMany(kvp => kvp.Value);
                    foreach (var parameter in unusedParameters)
                    {
                        var diagnostic = Diagnostic.Create(Rule, parameter.Locations[0], parameter.Name, parameter.ContainingSymbol.Name);
                        compilationAnalysisContext.ReportDiagnostic(diagnostic);
                    }
                });
            });
        }
示例#30
0
        private static async Task <Document> AddSerializableAttributeToType(Document document, ITypeSymbol type, CancellationToken cancellationToken)
        {
            SymbolEditor editor = SymbolEditor.Create(document);
            await editor.EditOneDeclarationAsync(type, (docEditor, declaration) =>
            {
                SyntaxNode serializableAttr = docEditor.Generator.Attribute(docEditor.Generator.TypeExpression(WellKnownTypes.SerializableAttribute(docEditor.SemanticModel.Compilation)));
                docEditor.AddAttribute(declaration, serializableAttr);
            }, cancellationToken).ConfigureAwait(false);

            return(editor.GetChangedDocuments().First());
        }