From 986e69971690831661b691c2a51d4a506860643a Mon Sep 17 00:00:00 2001 From: beakona Date: Fri, 18 Jun 2021 17:43:49 +0200 Subject: [PATCH] bug with dotted namespaces.. --- AutoInterfaceSample/Program.cs | 4 +- .../AutoInterfaceSourceGenerator.cs | 42 ++-- .../CSharpCodeTextWriter.cs | 221 ++++++++++-------- BeaKona.AutoInterfaceGenerator/Helpers.cs | 2 +- .../ICodeTextWriter.cs | 2 +- .../SemanticFacts.cs | 12 +- .../SourceBuilder.cs | 10 +- 7 files changed, 158 insertions(+), 135 deletions(-) diff --git a/AutoInterfaceSample/Program.cs b/AutoInterfaceSample/Program.cs index 9e781e5..2db261a 100644 --- a/AutoInterfaceSample/Program.cs +++ b/AutoInterfaceSample/Program.cs @@ -37,8 +37,8 @@ private void LogDebug(string name) } [BeaKona.AutoInterface] - [BeaKona.AutoInterfaceTemplate(BeaKona.AutoInterfaceTargets.PropertyGetter, Filter = "Length", Language = "scriban", Body = "return 1;")] - [BeaKona.AutoInterfaceTemplate(BeaKona.AutoInterfaceTargets.Method, Filter = "Print(\\d)?", Body = "LogDebug(nameof({{interface}}.{{name}})); {{expression}};")] + //[BeaKona.AutoInterfaceTemplate(BeaKona.AutoInterfaceTargets.PropertyGetter, Filter = "Length", Language = "scriban", Body = "return 1;")] + //[BeaKona.AutoInterfaceTemplate(BeaKona.AutoInterfaceTargets.Method, Filter = "Print(\\d)?", Body = "LogDebug(nameof({{interface}}.{{name}})); {{expression}};")] private readonly IPrintable? aspect1 = new PrinterV1(); //[BeaKona.AutoInterfaceTemplate(BeaKona.AutoInterfaceTargets.Method, Filter = "Print2", Body = "/* */")] diff --git a/BeaKona.AutoInterfaceGenerator/AutoInterfaceSourceGenerator.cs b/BeaKona.AutoInterfaceGenerator/AutoInterfaceSourceGenerator.cs index ed7e060..2c07273 100644 --- a/BeaKona.AutoInterfaceGenerator/AutoInterfaceSourceGenerator.cs +++ b/BeaKona.AutoInterfaceGenerator/AutoInterfaceSourceGenerator.cs @@ -26,7 +26,7 @@ public void Initialize(GeneratorInitializationContext context) public void Execute(GeneratorExecutionContext context) { using Stream icStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BeaKona.AutoInterfaceGenerator.InjectedCode.cs"); - using StreamReader icReader = new StreamReader(icStream); + using StreamReader icReader = new(icStream); SourceText txt = SourceText.From(icReader.ReadToEnd(), Encoding.UTF8); @@ -50,7 +50,7 @@ public void Execute(GeneratorExecutionContext context) if (compilation.GetTypeByMetadataName("BeaKona.AutoInterfaceAttribute") is INamedTypeSymbol autoInterfaceAttributeSymbol && compilation.GetTypeByMetadataName("BeaKona.AutoInterfaceTemplateAttribute") is INamedTypeSymbol autoInterfaceTemplateAttributeSymbol) { // loop over the candidates, and keep the ones that are actually annotated - List records = new List(); + List records = new(); foreach (MemberDeclarationSyntax candidate in receiver.Candidates) { @@ -125,7 +125,7 @@ public void Execute(GeneratorExecutionContext context) if (referencesWithMissingInterface.Count > 0) { - HashSet emitted = new HashSet(); + HashSet emitted = new(); foreach (AutoInterfaceRecord itemWithMissingInterface in referencesWithMissingInterface) { if (emitted.Add(itemWithMissingInterface.InterfaceType)) @@ -161,7 +161,7 @@ public void Execute(GeneratorExecutionContext context) //private static void GeneratePreview(GeneratorExecutionContext context, string name, string code) //{ - // StringBuilder output = new StringBuilder(); + // StringBuilder output = new(); // output.AppendLine("namespace BeaKona.Output {"); // output.AppendLine($"public static class Debug_{name}"); // output.AppendLine("{"); @@ -173,8 +173,8 @@ public void Execute(GeneratorExecutionContext context) private static List CollectRecords(GeneratorExecutionContext context, ISymbol symbol, ITypeSymbol receiverType, INamedTypeSymbol autoInterfaceAttributeSymbol, INamedTypeSymbol autoInterfaceTemplateAttributeSymbol) { - List templateParts = new List(); - Dictionary> danglingInterfaceTypesBySymbols = new Dictionary>(); + List templateParts = new(); + Dictionary> danglingInterfaceTypesBySymbols = new(); foreach (AttributeData attribute in symbol.GetAttributes()) { @@ -353,7 +353,7 @@ private static List CollectRecords(GeneratorExecutionContex } } - List records = new List(); + List records = new(); foreach (AttributeData attribute in symbol.GetAttributes()) { @@ -513,9 +513,9 @@ private static List CollectRecords(GeneratorExecutionContex private static string? ProcessClass(GeneratorExecutionContext context, Compilation compilation, INamedTypeSymbol type, IEnumerable infos) { - ScopeInfo scope = new ScopeInfo(type); + ScopeInfo scope = new(type); - SourceBuilder builder = new SourceBuilder(); + SourceBuilder builder = new(); ICodeTextWriter writer = new CSharpCodeTextWriter(context, compilation); bool anyReasonToEmitSourceFile = false; @@ -523,14 +523,10 @@ private static List CollectRecords(GeneratorExecutionContex //bool isNullable = compilation.Options.NullableContextOptions == NullableContextOptions.Enable; builder.AppendLine("#nullable enable"); + builder.AppendLine(); + writer.WriteNamespaceBeginning(builder, type.ContainingNamespace); - ImmutableArray namespaceParts = type.ContainingNamespace != null && type.ContainingNamespace.IsGlobalNamespace == false ? SemanticFacts.GetNamespaceParts(type.ContainingNamespace) : new ImmutableArray(); - if (namespaceParts.Length > 0) - { - writer.WriteNamespaceBeginning(builder, namespaceParts); - } - - List containingTypes = new List(); + List containingTypes = new(); for (INamedTypeSymbol? ct = type.ContainingType; ct != null; ct = ct.ContainingType) { containingTypes.Insert(0, ct); @@ -584,13 +580,13 @@ private static List CollectRecords(GeneratorExecutionContex { INamedTypeSymbol @interface = group.Key; - StandaloneModel model = new StandaloneModel(); + StandaloneModel model = new(); model.Load(writer, builder, @interface, scope, references); MethodModel CreateMethod(IMethodSymbol method) { - MethodModel m = new MethodModel(); + MethodModel m = new(); m.Load(writer, builder, method, scope, references); return m; } @@ -598,21 +594,21 @@ MethodModel CreateMethod(IMethodSymbol method) PropertyModel CreateProperty(IPropertySymbol property) { - PropertyModel m = new PropertyModel(); + PropertyModel m = new(); m.Load(writer, builder, property, scope, references); return m; } IndexerModel CreateIndexer(IPropertySymbol indexer) { - IndexerModel m = new IndexerModel(); + IndexerModel m = new(); m.Load(writer, builder, indexer, scope, references); return m; } EventModel CreateEvent(IEventSymbol @event) { - EventModel m = new EventModel(); + EventModel m = new(); m.Load(writer, builder, @event, scope, references); return m; } @@ -697,7 +693,7 @@ EventModel CreateEvent(IEventSymbol @event) builder.AppendLine('}'); } - if (namespaceParts.Length > 0) + if (type.ContainingNamespace != null && type.ContainingNamespace.ConstituentNamespaces.Length > 0) { builder.DecrementIndentation(); builder.AppendIndentation(); @@ -713,7 +709,7 @@ EventModel CreateEvent(IEventSymbol @event) /// private class SyntaxReceiver : ISyntaxReceiver { - public List Candidates { get; } = new List(); + public List Candidates { get; } = new(); /// /// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation diff --git a/BeaKona.AutoInterfaceGenerator/CSharpCodeTextWriter.cs b/BeaKona.AutoInterfaceGenerator/CSharpCodeTextWriter.cs index 8977232..138d632 100644 --- a/BeaKona.AutoInterfaceGenerator/CSharpCodeTextWriter.cs +++ b/BeaKona.AutoInterfaceGenerator/CSharpCodeTextWriter.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; namespace BeaKona.AutoInterfaceGenerator { @@ -259,7 +260,7 @@ public void WriteCallParameters(SourceBuilder builder, IEnumerable references) { - ScopeInfo methodScope = new ScopeInfo(scope); + ScopeInfo methodScope = new(scope); if (method.IsGenericMethod) { @@ -311,9 +312,9 @@ public void WriteMethodDefinition(SourceBuilder builder, IMethodSymbol method, S { if (template != null) { - TemplatedSourceTextGenerator generator = new TemplatedSourceTextGenerator(template.Template); + TemplatedSourceTextGenerator generator = new(template.Template); - PartialMethodModel model = new PartialMethodModel(); + PartialMethodModel model = new(); model.Load(this, builder, @interface, scope, references); model.Load(this, builder, method, methodScope, references); @@ -472,7 +473,7 @@ public void WritePropertyDefinition(SourceBuilder builder, IPropertySymbol prope builder.IncrementIndentation(); try { - TemplatedSourceTextGenerator generator = new TemplatedSourceTextGenerator(getterTemplate.Template); + TemplatedSourceTextGenerator generator = new(getterTemplate.Template); IPropertyModel model = property.IsIndexer ? new PartialIndexerModel() : (IPropertyModel)new PartialPropertyModel(); if (model is IRootModel rootModel) @@ -513,7 +514,7 @@ public void WritePropertyDefinition(SourceBuilder builder, IPropertySymbol prope { if (setterTemplate != null) { - TemplatedSourceTextGenerator generator = new TemplatedSourceTextGenerator(setterTemplate.Template); + TemplatedSourceTextGenerator generator = new(setterTemplate.Template); IPropertyModel model = property.IsIndexer ? new PartialIndexerModel() : (IPropertyModel)new PartialPropertyModel(); if (model is IRootModel rootModel) { @@ -604,8 +605,8 @@ public void WriteEventDefinition(SourceBuilder builder, IEventSymbol @event, Sco { if (adderTemplate != null) { - TemplatedSourceTextGenerator generator = new TemplatedSourceTextGenerator(adderTemplate.Template); - PartialEventModel model = new PartialEventModel(); + TemplatedSourceTextGenerator generator = new(adderTemplate.Template); + PartialEventModel model = new(); model.Load(this, builder, @interface, scope, references); model.Load(this, builder, @event, scope, references); @@ -646,8 +647,8 @@ public void WriteEventDefinition(SourceBuilder builder, IEventSymbol @event, Sco { if (removerTemplate != null) { - TemplatedSourceTextGenerator generator = new TemplatedSourceTextGenerator(removerTemplate.Template); - PartialEventModel model = new PartialEventModel(); + TemplatedSourceTextGenerator generator = new(removerTemplate.Template); + PartialEventModel model = new(); model.Load(this, builder, @interface, scope, references); model.Load(this, builder, @event, scope, references); @@ -712,15 +713,18 @@ public void WriteTypeDeclarationBeginning(SourceBuilder builder, INamedTypeSymbo this.WriteTypeReference(builder, type, scope); } - public void WriteNamespaceBeginning(SourceBuilder builder, IEnumerable @namespace) + public void WriteNamespaceBeginning(SourceBuilder builder, INamespaceSymbol @namespace) { - builder.AppendIndentation(); - builder.Append("namespace"); - builder.Append(' '); - builder.AppendLine(string.Join(".", @namespace.Select(i => this.GetSourceIdentifier(i)))); - builder.AppendIndentation(); - builder.AppendLine('{'); - builder.IncrementIndentation(); + if (@namespace != null && @namespace.ConstituentNamespaces.Length > 0) + { + builder.AppendIndentation(); + builder.Append("namespace"); + builder.Append(' '); + builder.AppendLine(GetSourceIdentifier(@namespace)); + builder.AppendIndentation(); + builder.AppendLine('{'); + builder.IncrementIndentation(); + } } public void WriteHolderReference(SourceBuilder builder, ISymbol member, ScopeInfo scope) @@ -864,107 +868,140 @@ public void WriteRefKind(SourceBuilder builder, RefKind kind) private string GetSourceIdentifier(ISymbol symbol) { - if (symbol is IPropertySymbol property && property.IsIndexer) + if (symbol is IPropertySymbol propertySymbol && propertySymbol.IsIndexer) { return "this"; } - else if (this.IsVerbatim(symbol)) - { - return $"@{symbol.Name}"; - } else { - return symbol.Name; - } - } - - private bool IsVerbatim(ISymbol symbol) - { - foreach (SyntaxReference syntaxReference in symbol.DeclaringSyntaxReferences) - { - SyntaxNode syntax = syntaxReference.GetSyntax(); - if (syntax is BaseTypeDeclarationSyntax type) + foreach (SyntaxReference syntaxReference in symbol.DeclaringSyntaxReferences) { - return type.Identifier.IsVerbatimIdentifier(); - } - else if (syntax is MethodDeclarationSyntax method) - { - return method.Identifier.IsVerbatimIdentifier(); - } - else if (syntax is ParameterSyntax parameter) - { - return parameter.Identifier.IsVerbatimIdentifier(); - } - else if (syntax is VariableDeclaratorSyntax variableDeclarator) - { - return variableDeclarator.Identifier.IsVerbatimIdentifier(); - } - else if (syntax is VariableDeclarationSyntax variableDeclaration) - { - foreach (var variable in variableDeclaration.Variables) + SyntaxNode syntax = syntaxReference.GetSyntax(); + if (syntax is BaseTypeDeclarationSyntax type) + { + return this.GetSourceIdentifier(type.Identifier); + } + else if (syntax is MethodDeclarationSyntax method) + { + return this.GetSourceIdentifier(method.Identifier); + } + else if (syntax is ParameterSyntax parameter) + { + return this.GetSourceIdentifier(parameter.Identifier); + } + else if (syntax is VariableDeclaratorSyntax variableDeclarator) { - if (variable.Identifier.IsVerbatimIdentifier()) + return this.GetSourceIdentifier(variableDeclarator.Identifier); + } + else if (syntax is VariableDeclarationSyntax variableDeclaration) + { + if (variableDeclaration.Variables.Any(i => i.Identifier.IsVerbatimIdentifier())) + { + return "@" + symbol; + } + else { - return true; + return symbol.ToString(); } } - - return false; - } - else if (syntax is BaseFieldDeclarationSyntax field) - { - foreach (var variable in field.Declaration.Variables) + else if (syntax is BaseFieldDeclarationSyntax field) { - if (variable.Identifier.IsVerbatimIdentifier()) + if (field.Declaration.Variables.Any(i => i.Identifier.IsVerbatimIdentifier())) + { + return "@" + symbol; + } + else { - return true; + return symbol.ToString(); } } - - return false; - } - else if (syntax is PropertyDeclarationSyntax property) - { - return property.Identifier.IsVerbatimIdentifier(); - } - else if (syntax is IndexerDeclarationSyntax) - { - throw new InvalidOperationException("trying to resolve indexer name"); - } - else if (syntax is EventDeclarationSyntax @event) - { - return @event.Identifier.IsVerbatimIdentifier(); - } - else if (syntax is TypeParameterSyntax typeParameter) - { - return typeParameter.Identifier.IsVerbatimIdentifier(); - } - else if (syntax is TupleTypeSyntax) - { - return false; - } - else if (syntax is TupleElementSyntax tupleElement) - { - return tupleElement.Identifier.IsVerbatimIdentifier(); + else if (syntax is PropertyDeclarationSyntax property) + { + return this.GetSourceIdentifier(property.Identifier); + } + else if (syntax is IndexerDeclarationSyntax) + { + throw new InvalidOperationException("trying to resolve indexer name"); + } + else if (syntax is EventDeclarationSyntax @event) + { + return this.GetSourceIdentifier(@event.Identifier); + } + else if (syntax is TypeParameterSyntax typeParameter) + { + return this.GetSourceIdentifier(typeParameter.Identifier); + } + else if (syntax is TupleTypeSyntax) + { + return symbol.Name; + } + else if (syntax is TupleElementSyntax tupleElement) + { + return this.GetSourceIdentifier(tupleElement.Identifier); + } + else if (syntax is NamespaceDeclarationSyntax @namespace) + { + return this.GetSourceIdentifier(@namespace.Name); + } + else + { + throw new NotSupportedException(syntax.GetType().ToString()); + } } - else if (syntax is NamespaceDeclarationSyntax @namespace) + + throw new NotSupportedException(); + } + } + + private string GetSourceIdentifier(SyntaxToken identifier) + { + if (identifier.IsVerbatimIdentifier()) + { + return "@" + identifier.ValueText; + } + else + { + return identifier.ValueText; + } + } + + private string GetSourceIdentifier(NameSyntax name) + { + if (name is SimpleNameSyntax simpleName) + { + return this.GetSourceIdentifier(simpleName.Identifier); + } + else if (name is QualifiedNameSyntax qualifiedName) + { + string left = this.GetSourceIdentifier(qualifiedName.Left); + string right = this.GetSourceIdentifier(qualifiedName.Right); + if (string.IsNullOrEmpty(left)) { - if (@namespace.Name is IdentifierNameSyntax identifier) + if (string.IsNullOrEmpty(right)) { - return identifier.Identifier.IsVerbatimIdentifier(); + throw new NotSupportedException("both are null_or_empty."); } else { - throw new NotSupportedException(syntax.GetType().ToString()); + return right; } } else { - throw new NotSupportedException(syntax.GetType().ToString()); + if (string.IsNullOrEmpty(right)) + { + return left; + } + else + { + return left + "." + right; + } } } - - return false; + else + { + throw new NotSupportedException(name.GetType().ToString()); + } } #endregion diff --git a/BeaKona.AutoInterfaceGenerator/Helpers.cs b/BeaKona.AutoInterfaceGenerator/Helpers.cs index 4c6fe1e..035da0f 100644 --- a/BeaKona.AutoInterfaceGenerator/Helpers.cs +++ b/BeaKona.AutoInterfaceGenerator/Helpers.cs @@ -21,7 +21,7 @@ public static void ReportDiagnostic(GeneratorExecutionContext context, string id LocalizableString? ldescription = new LocalizableResourceString(description, AutoInterfaceResource.ResourceManager, typeof(AutoInterfaceResource)); string category = typeof(AutoInterfaceSourceGenerator).Namespace; string? link = "https://github.com/beakona/AutoInterface"; - DiagnosticDescriptor dd = new DiagnosticDescriptor(id, ltitle, lmessage, category, severity, true, ldescription, link, WellKnownDiagnosticTags.NotConfigurable); + DiagnosticDescriptor dd = new(id, ltitle, lmessage, category, severity, true, ldescription, link, WellKnownDiagnosticTags.NotConfigurable); Diagnostic d = Diagnostic.Create(dd, location, messageArgs); context.ReportDiagnostic(d); } diff --git a/BeaKona.AutoInterfaceGenerator/ICodeTextWriter.cs b/BeaKona.AutoInterfaceGenerator/ICodeTextWriter.cs index 506ad32..fd60dca 100644 --- a/BeaKona.AutoInterfaceGenerator/ICodeTextWriter.cs +++ b/BeaKona.AutoInterfaceGenerator/ICodeTextWriter.cs @@ -25,7 +25,7 @@ internal interface ICodeTextWriter void WriteTypeDeclarationBeginning(SourceBuilder builder, INamedTypeSymbol type, ScopeInfo scope); - void WriteNamespaceBeginning(SourceBuilder builder, IEnumerable @namespace); + void WriteNamespaceBeginning(SourceBuilder builder, INamespaceSymbol @namespace); void WriteHolderReference(SourceBuilder builder, ISymbol member, ScopeInfo scope); diff --git a/BeaKona.AutoInterfaceGenerator/SemanticFacts.cs b/BeaKona.AutoInterfaceGenerator/SemanticFacts.cs index 348bf4d..b4570c3 100644 --- a/BeaKona.AutoInterfaceGenerator/SemanticFacts.cs +++ b/BeaKona.AutoInterfaceGenerator/SemanticFacts.cs @@ -53,7 +53,7 @@ public static ISymbol[] GetRelativeSymbols(ITypeSymbol type, ITypeSymbol scope) public static ISymbol[] GetContainingSymbols(ITypeSymbol type, bool includeSelf) { - List symbols = new List(); + List symbols = new(); for (ISymbol t = includeSelf ? type : type.ContainingSymbol; t != null; t = t.ContainingSymbol) { @@ -148,15 +148,5 @@ public static bool IsNullableT(Compilation compilation, INamedTypeSymbol type) return false; } - - public static ImmutableArray GetNamespaceParts(INamespaceSymbol @namespace) - { - List parts = new List(); - for (; @namespace != null && @namespace.IsGlobalNamespace == false; @namespace = @namespace.ContainingNamespace) - { - parts.Insert(0, @namespace); - } - return parts.ToImmutableArray(); - } } } diff --git a/BeaKona.AutoInterfaceGenerator/SourceBuilder.cs b/BeaKona.AutoInterfaceGenerator/SourceBuilder.cs index ed0b5af..f54c90c 100644 --- a/BeaKona.AutoInterfaceGenerator/SourceBuilder.cs +++ b/BeaKona.AutoInterfaceGenerator/SourceBuilder.cs @@ -25,8 +25,8 @@ private SourceBuilder(SourceBuilder owner, SourceBuilderOptions options) : this( public SourceBuilderOptions Options { get; } - private readonly List elements = new List(); - private readonly HashSet aliases = new HashSet(); + private readonly List elements = new(); + private readonly HashSet aliases = new(); public void Clear() { @@ -113,7 +113,7 @@ public void AppendIndentation() public SourceBuilder AppendNewBuilder(bool register = true) { - SourceBuilder builder = new SourceBuilder(this, this.Options); + SourceBuilder builder = new(this, this.Options); if (register) { this.elements.Add(builder); @@ -133,7 +133,7 @@ public SourceBuilder AppendBuilder(Action builder) public override string ToString() { - StringBuilder text = new StringBuilder(); + StringBuilder text = new(); foreach (string alias in this.aliases.OrderByDescending(i => i)) { text.Append("extern alias "); @@ -172,7 +172,7 @@ private void Write(StringBuilder builder) int depth = indentation.Depth; if (cache.TryGetValue(depth, out string value) == false) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new(); for (int i = 0; i < depth; i++) { sb.Append(this.Options.Identation);