using Microsoft.TypeSpec.Generator.ClientModel; using Microsoft.TypeSpec.Generator.EmitterRpc; using Microsoft.TypeSpec.Generator.Primitives; using Microsoft.TypeSpec.Generator.Providers; using System.Collections.Generic; using System.Text; namespace OpenAILibraryPlugin.Visitors; /// /// A visitor that throws an exception if a generated namespace is prohibited. This happens when a newly introduced /// type isn't emplaced into its appropriate namespace. Custom code definitions, including stubs that only emplace in /// namespaces, are exempt and will cause the generated code to be accepted. /// public class ProhibitedNamespaceVisitor : ScmLibraryVisitor { protected override TypeProvider VisitType(TypeProvider type) { HashSet violatingTypes = []; bool isPublicType = type.DeclarationModifiers.HasFlag(TypeSignatureModifiers.Public); bool isUnknownPrefixedType = type.Type.Name.StartsWith("Unknown"); if ((isPublicType || isUnknownPrefixedType) && (type.Type.Namespace == "OpenAI" || type.Type.Namespace == "OpenAI.Models") && string.IsNullOrEmpty(type.CustomCodeView?.Type.Namespace) && type.Type.Name != "OpenAIContext" && !violatingTypes.Contains(type)) { violatingTypes.Add(type); StringBuilder builder = new(); builder.Append($"[CodeGenType(\"{type.Name}\")] internal "); builder.Append(type.Type.IsValueType ? "readonly partial struct " : "partial class "); builder.AppendLine($"Internal{type.Name} {{}}"); OpenAILibraryGenerator.Instance.Emitter.ReportDiagnostic("prohibited-namespace", builder.ToString(), severity: EmitterDiagnosticSeverity.Error); } return type; } }