private void AnalyzeInvokedMember(
            OperationAnalysisContext context,
            InfoCache infoCache,
            IOperation?instance,
            IMethodSymbol?targetMethod,
            IOperation argumentValue,
            IPropertySymbol?lengthLikeProperty,
            CancellationToken cancellationToken)
        {
            // look for `s[s.Length - value]` or `s.Get(s.Length- value)`.

            // Needs to have the one arg for `s.Length - value`, and that arg needs to be
            // a subtraction.
            if (instance is null ||
                !IsSubtraction(argumentValue, out var subtraction))
            {
                return;
            }

            if (subtraction.Syntax is not BinaryExpressionSyntax binaryExpression)
            {
                return;
            }

            // Don't bother analyzing if the user doesn't like using Index/Range operators.
            var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferIndexOperator, binaryExpression.SyntaxTree, cancellationToken);

            if (!option.Value)
            {
                return;
            }

            // Ok, looks promising.  We're indexing in with some subtraction expression. Examine the
            // type this indexer is in to see if there's another member that takes a System.Index
            // that we can convert to.
            //
            // Also ensure that the left side of the subtraction : `s.Length - value` is actually
            // getting the length off the same instance we're indexing into.

            lengthLikeProperty ??= TryGetLengthLikeProperty(infoCache, targetMethod);
            if (lengthLikeProperty == null ||
                !IsInstanceLengthCheck(lengthLikeProperty, instance, subtraction.LeftOperand))
            {
                return;
            }

            if (CSharpSemanticFacts.Instance.IsInExpressionTree(instance.SemanticModel, instance.Syntax, infoCache.ExpressionOfTType, cancellationToken))
            {
                return;
            }

            // Everything looks good.  We can update this to use the System.Index member instead.
            context.ReportDiagnostic(
                DiagnosticHelper.Create(
                    Descriptor,
                    binaryExpression.GetLocation(),
                    option.Notification.Severity,
                    ImmutableArray <Location> .Empty,
                    ImmutableDictionary <string, string?> .Empty));
        }
Exemple #2
0
        public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.EnableConcurrentExecution();
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            analysisContext.RegisterOperationAction(context =>
            {
                var init           = (IFieldInitializerOperation)context.Operation;
                IFieldSymbol?field = init.InitializedFields.FirstOrDefault();
                if (field != null &&
                    !field.IsConst &&
                    init.Value != null &&
                    field.GetAttributes().IsEmpty&&  // in case of attributes that impact nullability analysis
                    UsesKnownDefaultValue(init.Value, field.Type))
                {
                    context.ReportDiagnostic(init.CreateDiagnostic(DefaultRule, field.Name));
                }
            }, OperationKind.FieldInitializer);

            analysisContext.RegisterOperationAction(context =>
            {
                var init             = (IPropertyInitializerOperation)context.Operation;
                IPropertySymbol?prop = init.InitializedProperties.FirstOrDefault();
                if (prop != null &&
                    init.Value != null &&
                    prop.GetAttributes().IsEmpty&&  // in case of attributes that impact nullability analysis
                    UsesKnownDefaultValue(init.Value, prop.Type))
                {
                    context.ReportDiagnostic(init.CreateDiagnostic(DefaultRule, prop.Name));
                }
            }, OperationKind.PropertyInitializer);
 private static bool TryDecodeOSPlatform(
     ImmutableArray <IArgumentOperation> arguments,
     INamedTypeSymbol osPlatformType,
     [NotNullWhen(returnValue: true)] out IPropertySymbol?osPlatformProperty)
 {
     Debug.Assert(!arguments.IsEmpty);
     return(TryDecodeOSPlatform(arguments[0].Value, osPlatformType, out osPlatformProperty));
 }
Exemple #4
0
        internal Getter(IFieldSymbol field)
        {
            Method   = null;
            Property = null;
            Field    = field;

            ForType = field.Type;
        }
Exemple #5
0
        internal Getter(IPropertySymbol prop)
        {
            Method   = null;
            Property = prop;
            Field    = null;

            ForType = prop.Type;
        }
Exemple #6
0
        /// <summary>
        /// Try finding the <see cref="IPropertySymbol"/> by name.
        /// </summary>
        /// <param name="type">The containing type.</param>
        /// <param name="name">The name of the property.</param>
        /// <param name="property">The match.</param>
        /// <returns>True if a match was found.</returns>
        public static bool TryFindProperty(this ITypeSymbol type, string name, [NotNullWhen(true)] out IPropertySymbol?property)
        {
            if (name == "Item[]")
            {
                return(type.TryFindFirstMember(x => x.IsIndexer, out property));
            }

            return(type.TryFindFirstMember(name, out property));
        }
Exemple #7
0
        internal Setter(IPropertySymbol prop)
        {
            Method    = null;
            Property  = prop;
            Field     = null;
            Parameter = null;

            ValueType = prop.Type;
        }
        private static bool IsSpecifiedPropertyDerived([NotNullWhen(returnValue: true)] IPropertySymbol?symbol, [NotNullWhen(returnValue: true)] INamedTypeSymbol?namedType, string propertyName)
        {
            if (symbol != null && namedType != null)
            {
                return(symbol.MatchPropertyDerivedByName(namedType, propertyName));
            }

            return(false);
        }
Exemple #9
0
        internal Setter(IParameterSymbol parameter)
        {
            Method    = null;
            Property  = null;
            Field     = null;
            Parameter = parameter;

            ValueType = parameter.Type;
        }
Exemple #10
0
        internal Setter(IFieldSymbol field)
        {
            Method    = null;
            Property  = null;
            Field     = field;
            Parameter = null;

            ValueType = field.Type;
        }
            protected sealed override SymbolKeyResolution Resolve(
                SymbolKeyReader reader, IPropertySymbol?contextualSymbol, out string?failureReason)
            {
                var metadataName = reader.ReadString();

                var containingTypeResolution = reader.ReadSymbolKey(contextualSymbol?.ContainingSymbol, out var containingTypeFailureReason);

                var isIndexer = reader.ReadBoolean();

                using var refKinds = reader.ReadRefKindArray();

                using var properties = GetMembersOfNamedType <IPropertySymbol>(containingTypeResolution, metadataName: null);
                using var result     = PooledArrayBuilder <IPropertySymbol> .GetInstance();

                // For each property that we look at, we'll have to resolve the parameter list and return type in the
                // context of that method.  This makes sure we can attempt to resolve the parameter list types against
                // error types in the property we're currently looking at.
                //
                // Because of this, we keep track of where we are in the reader.  Before resolving every parameter list,
                // we'll mark which method we're on and we'll rewind to this point.
                var beforeParametersPosition = reader.Position;

                IPropertySymbol?property = null;

                foreach (var candidate in properties)
                {
                    if (candidate.Parameters.Length != refKinds.Count ||
                        candidate.MetadataName != metadataName ||
                        candidate.IsIndexer != isIndexer ||
                        !ParameterRefKindsMatch(candidate.OriginalDefinition.Parameters, refKinds))
                    {
                        continue;
                    }

                    property = Resolve(reader, candidate);
                    if (property != null)
                    {
                        break;
                    }

                    // reset ourselves so we can check the return-type/parameters against the next candidate.
                    reader.Position = beforeParametersPosition;
                }

                if (reader.Position == beforeParametersPosition)
                {
                    // We didn't find a match.  Read through the stream one final time so we're at the correct location
                    // after this PropertySymbolKey.

                    _ = reader.ReadSymbolKeyArray <IPropertySymbol, ITypeSymbol>(
                        contextualSymbol: null, getContextualSymbol: null, failureReason: out _);
                }

                if (containingTypeFailureReason != null)
                {
                    failureReason = $"({nameof(PropertySymbolKey)} {nameof(containingTypeResolution)} failed -> {containingTypeFailureReason})";
                    return(default);
 /// <summary>
 /// Determines if the given symbol is a backing field for a property.
 /// </summary>
 /// <param name="symbol">This symbol to check.</param>
 /// <param name="propertySymbol">The property that this field symbol is backing.</param>
 /// <returns>True if the given symbol is a backing field for a property, false otherwise.</returns>
 public static bool IsBackingFieldForProperty(
     [NotNullWhen(returnValue: true)] this ISymbol?symbol,
     [NotNullWhen(returnValue: true)] out IPropertySymbol?propertySymbol)
 {
     if (symbol is IFieldSymbol fieldSymbol &&
         fieldSymbol.IsImplicitlyDeclared &&
         fieldSymbol.AssociatedSymbol is IPropertySymbol p)
     {
         propertySymbol = p;
         return(true);
     }
Exemple #13
0
        internal Getter(IMethodSymbol method, bool takesRow, bool takesContext)
        {
            Method             = method;
            MethodTakesRow     = takesRow;
            MethodTakesContext = takesContext;

            ForType = method.ReturnType;

            Property = null;
            Field    = null;
        }
Exemple #14
0
        public sealed override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterOperationAction(context =>
            {
                var init           = (IFieldInitializerOperation)context.Operation;
                IFieldSymbol?field = init.InitializedFields.FirstOrDefault();
                if (field == null ||
                    field.IsConst ||
                    init.Value == null ||
                    !field.GetAttributes().IsEmpty)    // in case of attributes that impact nullability analysis
                {
                    return;
                }

                // Do not report on instance members of struct but report on static members.
                if (field.ContainingType?.TypeKind == TypeKind.Struct && !field.IsStatic)
                {
                    return;
                }

                if (UsesKnownDefaultValue(init.Value, field.Type))
                {
                    context.ReportDiagnostic(init.CreateDiagnostic(DefaultRule, field.Name));
                }
            }, OperationKind.FieldInitializer);

            context.RegisterOperationAction(context =>
            {
                var init             = (IPropertyInitializerOperation)context.Operation;
                IPropertySymbol?prop = init.InitializedProperties.FirstOrDefault();
                if (prop == null ||
                    init.Value == null ||
                    !prop.GetAttributes().IsEmpty)    // in case of attributes that impact nullability analysis
                {
                    return;
                }

                // Do not report on instance members of struct but report on static members.
                if (prop.ContainingType?.TypeKind == TypeKind.Struct && !prop.IsStatic)
                {
                    return;
                }

                if (UsesKnownDefaultValue(init.Value, prop.Type))
                {
                    context.ReportDiagnostic(init.CreateDiagnostic(DefaultRule, prop.Name));
                }
            }, OperationKind.PropertyInitializer);
        }
Exemple #15
0
        internal Setter(IMethodSymbol method, ITypeSymbol valueType, bool takesRow, bool takesRowByRef, bool takesContext)
        {
            Method              = method;
            MethodTakesRow      = takesRow;
            MethodTakesRowByRef = takesRowByRef;
            MethodTakesContext  = takesContext;

            ValueType = valueType;

            Property  = null;
            Field     = null;
            Parameter = null;
        }
        protected UpdateFieldGenerator(ISymbol enumerationSymbol, IPropertySymbol?propertySymbol, IUpdateFieldGenerator?previousField, int?cardinality = null)
        {
            EnumerationSymbol = enumerationSymbol;
            PropertySymbol    = propertySymbol;
            Cardinality       = cardinality;

            Offset = previousField != null
                ? $"{previousField.NextOffset}"
                : "0";

            NextOffset = Cardinality.HasValue
                ? $"{EnumerationSymbol.Name}[{Cardinality - 1}].BitEnd"
                : $"{EnumerationSymbol.Name}.BitEnd";
        }
            private static bool TryDecodeOSPlatform(
                IOperation argumentValue,
                INamedTypeSymbol osPlatformType,
                [NotNullWhen(returnValue: true)] out IPropertySymbol?osPlatformProperty)
            {
                if ((argumentValue is IPropertyReferenceOperation propertyReference) &&
                    propertyReference.Property.ContainingType.Equals(osPlatformType))
                {
                    osPlatformProperty = propertyReference.Property;
                    return(true);
                }

                osPlatformProperty = null;
                return(false);
            }
Exemple #18
0
        public static AttributeData?FindAttributeIncludeBasePropertyShortName(this IPropertySymbol?property, string typeName)
        {
            while (property != null)
            {
                var data = FindAttributeShortName(property.GetAttributes(), typeName);
                if (data != null)
                {
                    return(data);
                }

                property = property.OverriddenProperty;
            }

            return(null);
        }
Exemple #19
0
        public bool Equals(IPropertySymbol?property1, IPropertySymbol?property2)
        {
            if (ReferenceEquals(property1, property2))
            {
                return(true);
            }
            if (ReferenceEquals(property1, null) || ReferenceEquals(property2, null))
            {
                return(false);
            }

            var rootProperty1 = GetRootProperty(property1);
            var rootProperty2 = GetRootProperty(property2);

            return(rootProperty1.Equals(rootProperty2));
        }
Exemple #20
0
                void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol? containingPropertySymbol, IOperation operation, Action <Diagnostic> reportDiagnostic, bool useNamingHeuristic)
                {
                    if (ShouldBeLocalized(parameter.OriginalDefinition, containingPropertySymbol?.OriginalDefinition, localizableStateAttributeSymbol, conditionalAttributeSymbol, systemConsoleSymbol, typesToIgnore, useNamingHeuristic) &&
                        lazyValueContentResult.Value != null)
                    {
                        ValueContentAbstractValue stringContentValue = lazyValueContentResult.Value[operation.Kind, operation.Syntax];
                        if (stringContentValue.IsLiteralState)
                        {
                            Debug.Assert(!stringContentValue.LiteralValues.IsEmpty);

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

                            var stringLiteralValues = stringContentValue.LiteralValues.Cast <string?>();

                            // 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.
                            IEnumerable <string> filteredStrings = stringLiteralValues.Where(literal => literal != null && !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);
                            }
                        }
                    }
                }
        /// <summary> Determines equality by name, containing type and type. </summary>
        /// <param name="x">The first instance.</param>
        /// <param name="y">The other instance.</param>
        /// <returns>True if the instances are found equal.</returns>
        public static bool Equal(IPropertySymbol?x, IPropertySymbol?y)
        {
            if (ReferenceEquals(x, y))
            {
                return(true);
            }

            if (x is null ||
                y is null)
            {
                return(false);
            }

            return(x.MetadataName == y.MetadataName &&
                   NamedTypeSymbolComparer.Equal(x.ContainingType, y.ContainingType) &&
                   TypeSymbolComparer.Equal(x.Type, y.Type));
        }
Exemple #22
0
        public static bool IsIsCompletedFromAwaiterPattern(
            [NotNullWhen(true)] this IPropertySymbol?property,
            [NotNullWhen(true)] INamedTypeSymbol?inotifyCompletionType,
            [NotNullWhen(true)] INamedTypeSymbol?icriticalNotifyCompletionType)
        {
            if (property is null ||
                !property.Name.Equals("IsCompleted", StringComparison.Ordinal) ||
                property.Type?.SpecialType != SpecialType.System_Boolean)
            {
                return(false);
            }

            var containingType = property.ContainingType?.OriginalDefinition;

            return(containingType.DerivesFrom(inotifyCompletionType) ||
                   containingType.DerivesFrom(icriticalNotifyCompletionType));
        }
        private static bool TryGetDictionaryTypeAndMembers(Compilation compilation,
                                                           [NotNullWhen(true)] out INamedTypeSymbol?iDictionaryType,
                                                           [NotNullWhen(true)] out IMethodSymbol?containsKeySymbol,
                                                           [NotNullWhen(true)] out IPropertySymbol?indexerSymbol)
        {
            containsKeySymbol = null;
            indexerSymbol     = null;
            if (!compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIDictionary2, out iDictionaryType))
            {
                return(false);
            }

            containsKeySymbol = iDictionaryType.GetMembers().OfType <IMethodSymbol>().FirstOrDefault(m => m.Name == ContainsKey);
            indexerSymbol     = iDictionaryType.GetMembers().OfType <IPropertySymbol>().FirstOrDefault(m => m.Name == IndexerName || m.Language == LanguageNames.VisualBasic && m.Name == IndexerNameVb);

            return(containsKeySymbol is not null && indexerSymbol is not null);
        }
        /// <summary> Compares equality by name and containing type and treats overridden and definition as equal. </summary>
        /// <param name="x">The first instance.</param>
        /// <param name="y">The other instance.</param>
        /// <returns>True if the instances are found equal.</returns>
        public static bool Equivalent(IPropertySymbol?x, IPropertySymbol?y)
        {
            if (ReferenceEquals(x, y))
            {
                return(true);
            }

            if (x is null ||
                y is null)
            {
                return(false);
            }

            return(Equal(x, y) ||
                   Overridden(x, y) ||
                   Overridden(y, x) ||
                   Definition(x, y) ||
                   Definition(y, x));
        /// <summary>
        /// Try finding the <see cref="IPropertySymbol"/> by name.
        /// </summary>
        /// <param name="type">The containing type.</param>
        /// <param name="name">The name of the property.</param>
        /// <param name="property">The match.</param>
        /// <returns>True if a match was found.</returns>
        public static bool TryFindProperty(this ITypeSymbol type, string name, [NotNullWhen(true)] out IPropertySymbol?property)
        {
            if (type is null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException($"'{nameof(name)}' cannot be null or empty", nameof(name));
            }

            if (name == "Item[]")
            {
                return(type.TryFindFirstMember(x => x.IsIndexer, out property));
            }

            return(type.TryFindFirstMember(name, out property));
        }
Exemple #26
0
        protected ExpressionRewriter(
            IMethodSymbol method,
            InvocationExpressionSyntax invocationExpressionSyntax,
            CSharpCompilation compilation)
        {
            this.method = method;

            const int KEditorFirstLineNumber = 1;

            location = invocationExpressionSyntax.ArgumentList.GetLocation();
            var lineSpan = location.GetLineSpan();
            var al       = invocationExpressionSyntax.ArgumentList;

            var(lambdaSyntax, syntaxUidPart1, syntaxUidPart2) = (GetLambda(al), GetUidPart1(al), GetUidPart2(al));

            LiteralExpressionSyntax?le;
            var uidPart1 = syntaxUidPart1 == null || (le = LiteralExpressionLocator.Locate(syntaxUidPart1)) == null
                ? Path.GetFullPath(lineSpan.Path)
                : le.ToString()
                           .Replace("\"", "").Replace(@"\\", @"\"); // unescape string

            var uidPart2 = syntaxUidPart2 == null || (le = LiteralExpressionLocator.Locate(syntaxUidPart2)) == null
                ? (lineSpan.StartLinePosition.Line + KEditorFirstLineNumber).ToString()
                : le.ToString();

            using (var hash = SHA256.Create())
                className = '_' + Convert.ToBase64String(hash.ComputeHash(Encoding.UTF8.GetBytes(uidPart1)))
                            .Replace('+', 'ф').Replace('=', 'ы').Replace('/', 'п') // replace to random symbols that not prohibited by file system
                            + "_" + uidPart2;

            uid = uidPart2 + uidPart1;
            var(lambda, parameter) = LambdaLocator.Locate(lambdaSyntax);
            this.parameter         = parameter;
            assignment             = AssignmentLocator.Locate(lambda);

            if (assignment != null)
            {
                leftPart = compilation.GetSemanticModel(assignment.Left.SyntaxTree)
                           .GetSymbolInfo(assignment.Left).Symbol as IPropertySymbol;
            }
        }
Exemple #27
0
        private void CreateAnalyzerWithinCompilation(CompilationStartAnalysisContext context)
        {
            context.CancellationToken.ThrowIfCancellationRequested();

            INamedTypeSymbol?codeFixProviderSymbol = context.Compilation.GetOrCreateTypeByMetadataName(CodeFixProviderMetadataName);

            if (codeFixProviderSymbol == null)
            {
                return;
            }

            IMethodSymbol?getFixAllProviderMethod = codeFixProviderSymbol.GetMembers(GetFixAllProviderMethodName).OfType <IMethodSymbol>().FirstOrDefault();

            if (getFixAllProviderMethod == null)
            {
                return;
            }

            INamedTypeSymbol?codeActionSymbol = context.Compilation.GetOrCreateTypeByMetadataName(CodeActionMetadataName);

            if (codeActionSymbol == null)
            {
                return;
            }

            IPropertySymbol?equivalenceKeyProperty = codeActionSymbol.GetMembers(EquivalenceKeyPropertyName).OfType <IPropertySymbol>().FirstOrDefault();

            if (equivalenceKeyProperty == null)
            {
                return;
            }

            var createMethods = codeActionSymbol.GetMembers(CreateMethodName).OfType <IMethodSymbol>().ToImmutableHashSet();

            CompilationAnalyzer compilationAnalyzer = new CompilationAnalyzer(codeFixProviderSymbol, codeActionSymbol, context.Compilation.Assembly, createMethods);

            context.RegisterSymbolAction(compilationAnalyzer.AnalyzeNamedTypeSymbol, SymbolKind.NamedType);
            context.RegisterOperationBlockStartAction(compilationAnalyzer.OperationBlockStart);
            context.RegisterCompilationEndAction(compilationAnalyzer.CompilationEnd);
        }
        public static bool HasAttribute(this IPropertySymbol propertySymbol, ITypeSymbol attribute, bool inherit)
        {
            Debug.Assert(propertySymbol != null);
            Debug.Assert(attribute != null);

            if (!inherit)
            {
                return(HasAttribute(propertySymbol, attribute));
            }

            IPropertySymbol?current = propertySymbol;

            while (current != null)
            {
                if (current.HasAttribute(attribute))
                {
                    return(true);
                }

                current = current.IsOverride ? current.OverriddenProperty : null;
            }

            return(false);
        }
Exemple #29
0
        public static bool HasAttribute(this IPropertySymbol propertySymbol, ITypeSymbol attribute, bool inherit)
        {
            propertySymbol = propertySymbol ?? throw new ArgumentNullException(nameof(propertySymbol));
            attribute      = attribute ?? throw new ArgumentNullException(nameof(attribute));

            if (!inherit)
            {
                return(HasAttribute(propertySymbol, attribute));
            }

            IPropertySymbol?current = propertySymbol;

            while (current != null)
            {
                if (current.HasAttribute(attribute))
                {
                    return(true);
                }

                current = current.IsOverride ? current.OverriddenProperty : null;
            }

            return(false);
        }
 public static bool IsXsltSettingsEnableDocumentFunctionProperty([NotNullWhen(returnValue: true)] IPropertySymbol?symbol, CompilationSecurityTypes xmlTypes)
 {
     return(IsSpecifiedProperty(symbol, xmlTypes.XsltSettings, SecurityMemberNames.EnableDocumentFunction));
 }