/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/Test/Utilities/CSharp/TestAttributesVisitor.cs
220 строк
7 KB
Cyrus Najmabadi
Remove unnecessary suppressions (#81499)
02 дек 2025, 01:23
Не верифицирован
02 дек 2025, 01:23
3042fe7
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Text; using Microsoft.CodeAnalysis.CSharp.Symbols; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities { internal abstract class TestAttributesVisitor : CSharpSymbolVisitor { protected readonly StringBuilder _builder; protected readonly HashSet<Symbol> _reported; protected TestAttributesVisitor(StringBuilder builder) { _builder = builder; _reported = new HashSet<Symbol>(); } public override void DefaultVisit(Symbol symbol) { ReportSymbol(symbol); } public override void VisitModule(ModuleSymbol module) { Visit(module.GlobalNamespace); } public override void VisitNamespace(NamespaceSymbol @namespace) { VisitList(@namespace.GetMembers()); } public override void VisitNamedType(NamedTypeSymbol type) { ReportSymbol(type); VisitList(type.TypeParameters); foreach (var member in type.GetMembers()) { // Skip accessors since those are covered by associated symbol. if (member.IsAccessor()) continue; Visit(member); } } public override void VisitMethod(MethodSymbol method) { ReportSymbol(method); VisitList(method.TypeParameters); VisitList(method.Parameters); } public override void VisitEvent(EventSymbol @event) { ReportSymbol(@event); Visit(@event.AddMethod); Visit(@event.RemoveMethod); } public override void VisitProperty(PropertySymbol property) { ReportSymbol(property); VisitList(property.Parameters); Visit(property.GetMethod); Visit(property.SetMethod); } public override void VisitTypeParameter(TypeParameterSymbol typeParameter) { ReportSymbol(typeParameter); } private void VisitList<TSymbol>(ImmutableArray<TSymbol> symbols) where TSymbol : Symbol { foreach (var symbol in symbols) { Visit(symbol); } } /// <summary> /// Return the containing symbol used in the hierarchy here. Specifically, the /// hierarchy contains types, members, and parameters only, and accessors are /// considered members of the associated symbol rather than the type. /// </summary> private static Symbol? GetContainingSymbol(Symbol symbol) { if (symbol.IsAccessor()) { return ((MethodSymbol)symbol).AssociatedSymbol; } var containingSymbol = symbol.ContainingSymbol; return containingSymbol?.Kind == SymbolKind.Namespace ? null : containingSymbol; } protected static string GetIndentString(Symbol symbol) { int level = 0; var current = symbol; while (true) { current = GetContainingSymbol(current); if (current is null) { break; } level++; } return new string(' ', level * 4); } protected abstract SymbolDisplayFormat DisplayFormat { get; } protected void ReportContainingSymbols(Symbol symbol) { var s = GetContainingSymbol(symbol); if (s is null) { return; } if (_reported.Contains(s)) { return; } ReportContainingSymbols(s); _builder.Append(GetIndentString(s)); _builder.AppendLine(s.ToDisplayString(DisplayFormat)); _reported.Add(s); } protected virtual void ReportSymbol(Symbol symbol) { var type = (symbol as TypeSymbol) ?? symbol.GetTypeOrReturnType().Type; var attribute = GetTargetAttribute((symbol is MethodSymbol method) ? method.GetReturnTypeAttributes() : symbol.GetAttributes()); Debug.Assert((!TypeRequiresAttribute(type)) || (attribute != null)); if (attribute == null) { return; } ReportContainingSymbols(symbol); _builder.Append(GetIndentString(symbol)); _builder.Append($"{ReportAttribute(attribute)} "); _builder.AppendLine(symbol.ToDisplayString(DisplayFormat)); _reported.Add(symbol); } protected static string ReportAttribute(CSharpAttributeData attribute) { var builder = new StringBuilder(); builder.Append('['); Assert.NotNull(attribute.AttributeClass); var name = attribute.AttributeClass.Name; if (name.EndsWith("Attribute")) name = name.Substring(0, name.Length - 9); builder.Append(name); var arguments = attribute.ConstructorArguments.ToImmutableArray(); if (arguments.Length > 0) { builder.Append('('); printValues(builder, arguments); builder.Append(')'); } builder.Append(']'); return builder.ToString(); static void printValues(StringBuilder builder, ImmutableArray<TypedConstant> values) { for (int i = 0; i < values.Length; i++) { if (i > 0) { builder.Append(", "); } printValue(builder, values[i]); } } static void printValue(StringBuilder builder, TypedConstant value) { if (value.Kind == TypedConstantKind.Array) { builder.Append("{ "); printValues(builder, value.Values); builder.Append(" }"); } else { builder.Append(value.Value); } } } protected abstract bool TypeRequiresAttribute(TypeSymbol? type); protected abstract CSharpAttributeData? GetTargetAttribute(ImmutableArray<CSharpAttributeData> attributes); protected static CSharpAttributeData? GetAttribute(ImmutableArray<CSharpAttributeData> attributes, string namespaceName, string name) { foreach (var attribute in attributes) { Assert.NotNull(attribute.AttributeConstructor); var containingType = attribute.AttributeConstructor.ContainingType; if (containingType.Name == name && containingType.ContainingNamespace.QualifiedName == namespaceName) { return attribute; } } return null; } } }