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)); }
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)); }
internal Getter(IFieldSymbol field) { Method = null; Property = null; Field = field; ForType = field.Type; }
internal Getter(IPropertySymbol prop) { Method = null; Property = prop; Field = null; ForType = prop.Type; }
/// <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)); }
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); }
internal Setter(IParameterSymbol parameter) { Method = null; Property = null; Field = null; Parameter = parameter; ValueType = parameter.Type; }
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); }
internal Getter(IMethodSymbol method, bool takesRow, bool takesContext) { Method = method; MethodTakesRow = takesRow; MethodTakesContext = takesContext; ForType = method.ReturnType; Property = null; Field = null; }
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); }
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); }
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); }
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)); }
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)); }
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)); }
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; } }
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); }
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)); }