diff --git a/InterfaceStubGenerator.Shared/InterfaceStubGenerator.Shared.projitems b/InterfaceStubGenerator.Shared/InterfaceStubGenerator.Shared.projitems index 8eab43eb8..f4cfc6944 100644 --- a/InterfaceStubGenerator.Shared/InterfaceStubGenerator.Shared.projitems +++ b/InterfaceStubGenerator.Shared/InterfaceStubGenerator.Shared.projitems @@ -21,6 +21,7 @@ + diff --git a/InterfaceStubGenerator.Shared/Models/WellKnownTypes.cs b/InterfaceStubGenerator.Shared/Models/WellKnownTypes.cs new file mode 100644 index 000000000..28ea5e403 --- /dev/null +++ b/InterfaceStubGenerator.Shared/Models/WellKnownTypes.cs @@ -0,0 +1,30 @@ +using Microsoft.CodeAnalysis; + +namespace Refit.Generator; + +public class WellKnownTypes(Compilation compilation) +{ + readonly Dictionary cachedTypes = new(); + + public INamedTypeSymbol Get() => Get(typeof(T)); + public INamedTypeSymbol Get(Type type) + { + return Get(type.FullName ?? throw new InvalidOperationException("Could not get name of type " + type)); + } + + public INamedTypeSymbol? TryGet(string typeFullName) + { + if (cachedTypes.TryGetValue(typeFullName, out var typeSymbol)) + { + return typeSymbol; + } + + typeSymbol = compilation.GetTypeByMetadataName(typeFullName); + cachedTypes.Add(typeFullName, typeSymbol); + + return typeSymbol; + } + + INamedTypeSymbol Get(string typeFullName) => + TryGet(typeFullName) ?? throw new InvalidOperationException("Could not get type " + typeFullName); +} diff --git a/InterfaceStubGenerator.Shared/Parser.cs b/InterfaceStubGenerator.Shared/Parser.cs index 2d1dd0515..280c74d9b 100644 --- a/InterfaceStubGenerator.Shared/Parser.cs +++ b/InterfaceStubGenerator.Shared/Parser.cs @@ -32,6 +32,8 @@ CancellationToken cancellationToken if (compilation == null) throw new ArgumentNullException(nameof(compilation)); + var wellKnownTypes = new WellKnownTypes(compilation); + refitInternalNamespace = $"{refitInternalNamespace ?? string.Empty}RefitInternalGenerated"; // Remove - as they are valid in csproj, but invalid in a namespace @@ -41,8 +43,8 @@ CancellationToken cancellationToken // TODO: we should allow source generators to provide source during initialize, so that this step isn't required. var options = (CSharpParseOptions)compilation.SyntaxTrees[0].Options; - var disposableInterfaceSymbol = compilation.GetTypeByMetadataName("System.IDisposable")!; - var httpMethodBaseAttributeSymbol = compilation.GetTypeByMetadataName( + var disposableInterfaceSymbol = wellKnownTypes.Get(typeof(IDisposable)); + var httpMethodBaseAttributeSymbol = wellKnownTypes.TryGet( "Refit.HttpMethodAttribute" );