private static LocalizableAttributeState GetLocalizableAttributeState(ISymbol symbol, INamedTypeSymbol localizableAttributeTypeSymbol) { Debug.Assert(localizableAttributeTypeSymbol != null); if (symbol == null) { return(LocalizableAttributeState.Undefined); } LocalizableAttributeState localizedState = GetLocalizableAttributeStateCore(symbol.GetAttributes(), localizableAttributeTypeSymbol); if (localizedState != LocalizableAttributeState.Undefined) { return(localizedState); } ISymbol containingSymbol = (symbol as IMethodSymbol)?.AssociatedSymbol is IPropertySymbol propertySymbol ? propertySymbol : symbol.ContainingSymbol; return(GetLocalizableAttributeState(containingSymbol, localizableAttributeTypeSymbol)); }
private static bool ShouldBeLocalized( IParameterSymbol parameterSymbol, IPropertySymbol containingPropertySymbolOpt, INamedTypeSymbol localizableStateAttributeSymbol, INamedTypeSymbol conditionalAttributeSymbol, INamedTypeSymbol systemConsoleSymbol, ImmutableHashSet <INamedTypeSymbol> typesToIgnore) { Debug.Assert(parameterSymbol.ContainingSymbol.Kind == SymbolKind.Method); if (parameterSymbol.Type.SpecialType != SpecialType.System_String) { return(false); } // Verify LocalizableAttributeState if (localizableStateAttributeSymbol != null) { LocalizableAttributeState localizableAttributeState = GetLocalizableAttributeState(parameterSymbol, localizableStateAttributeSymbol); switch (localizableAttributeState) { case LocalizableAttributeState.False: return(false); case LocalizableAttributeState.True: return(true); default: break; } } // FxCop compat checks. if (typesToIgnore.Contains(parameterSymbol.ContainingType) || parameterSymbol.ContainingSymbol.HasAttribute(conditionalAttributeSymbol)) { return(false); } // FxCop compat: For overrides, check for localizability of the corresponding parameter in the overridden method. var method = (IMethodSymbol)parameterSymbol.ContainingSymbol; if (method.IsOverride && method.OverriddenMethod?.Parameters.Length == method.Parameters.Length) { int parameterIndex = method.GetParameterIndex(parameterSymbol); IParameterSymbol overridenParameter = method.OverriddenMethod.Parameters[parameterIndex]; if (Equals(overridenParameter.Type, parameterSymbol.Type)) { return(ShouldBeLocalized(overridenParameter, containingPropertySymbolOpt, localizableStateAttributeSymbol, conditionalAttributeSymbol, systemConsoleSymbol, typesToIgnore)); } } // FxCop compat: If a localizable attribute isn't defined then fall back to name heuristics. bool IsLocalizableByNameHeuristic(ISymbol symbol) => symbol.Name.Equals("message", StringComparison.OrdinalIgnoreCase) || symbol.Name.Equals("text", StringComparison.OrdinalIgnoreCase) || symbol.Name.Equals("caption", StringComparison.OrdinalIgnoreCase); if (IsLocalizableByNameHeuristic(parameterSymbol) || containingPropertySymbolOpt != null && IsLocalizableByNameHeuristic(containingPropertySymbolOpt)) { return(true); } if (method.ContainingType.Equals(systemConsoleSymbol) && (method.Name.Equals("Write", StringComparison.Ordinal) || method.Name.Equals("WriteLine", StringComparison.Ordinal)) && (parameterSymbol.Name.Equals("format", StringComparison.OrdinalIgnoreCase) || parameterSymbol.Name.Equals("value", StringComparison.OrdinalIgnoreCase))) { return(true); } return(false); }