Merge pull request #1216 from sharwell/multi-target
Support Roslyn 3.8 and Roslyn 4.0 source generator scenarios
This commit is contained in:
Коммит
150dd1f450
|
@ -2,6 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<AssemblyName>InterfaceStubGeneratorV1</AssemblyName>
|
||||
<RootNamespace>Refit.Generator</RootNamespace>
|
||||
<IsPackable>false</IsPackable>
|
||||
<AssemblyOriginatorKeyFile>..\buildtask.snk</AssemblyOriginatorKeyFile>
|
||||
|
@ -21,4 +22,6 @@
|
|||
</PropertyGroup>
|
||||
</Target>
|
||||
|
||||
<Import Project="..\InterfaceStubGenerator.Shared\InterfaceStubGenerator.Shared.projitems" Label="Shared" />
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,28 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<AssemblyName>InterfaceStubGeneratorV2</AssemblyName>
|
||||
<RootNamespace>Refit.Generator</RootNamespace>
|
||||
<IsPackable>false</IsPackable>
|
||||
<AssemblyOriginatorKeyFile>..\buildtask.snk</AssemblyOriginatorKeyFile>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<IsRoslynComponent>true</IsRoslynComponent>
|
||||
<Nullable>enable</Nullable>
|
||||
<DefineConstants>$(DefineConstants);ROSLYN_4</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.0-2.final" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="SetBuildVer" AfterTargets="GetBuildVersion" BeforeTargets="SetCloudBuildVersionVars;SetCloudBuildNumberWithVersion">
|
||||
<PropertyGroup>
|
||||
<Version>$(BuildVersion)</Version>
|
||||
<AssemblyVersion>$(BuildVersionSimple)</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
|
||||
<Import Project="..\InterfaceStubGenerator.Shared\InterfaceStubGenerator.Shared.projitems" Label="Shared" />
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' < '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<HasSharedItems>true</HasSharedItems>
|
||||
<SharedGUID>b591423d-f92d-4e00-b0eb-615c9853506c</SharedGUID>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<Import_RootNamespace>InterfaceStubGenerator.Shared</Import_RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)InterfaceStubGenerator.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ITypeSymbolExtensions.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>b591423d-f92d-4e00-b0eb-615c9853506c</ProjectGuid>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
|
||||
<PropertyGroup />
|
||||
<Import Project="InterfaceStubGenerator.Shared.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
|
||||
</Project>
|
|
@ -17,13 +17,17 @@ namespace Refit.Generator
|
|||
// defn's
|
||||
|
||||
[Generator]
|
||||
#if ROSLYN_4
|
||||
public class InterfaceStubGeneratorV2 : IIncrementalGenerator
|
||||
#else
|
||||
public class InterfaceStubGenerator : ISourceGenerator
|
||||
#endif
|
||||
{
|
||||
#pragma warning disable RS2008 // Enable analyzer release tracking
|
||||
static readonly DiagnosticDescriptor InvalidRefitMember = new(
|
||||
"RF001",
|
||||
"Refit types must have Refit HTTP method attributes",
|
||||
"Method {0}.{1} either has no Refit HTTP method attribute or you've used something other than a string literal for the 'path' argument.",
|
||||
"Method {0}.{1} either has no Refit HTTP method attribute or you've used something other than a string literal for the 'path' argument",
|
||||
"Refit",
|
||||
DiagnosticSeverity.Warning,
|
||||
true);
|
||||
|
@ -37,40 +41,59 @@ namespace Refit.Generator
|
|||
true);
|
||||
#pragma warning restore RS2008 // Enable analyzer release tracking
|
||||
|
||||
public void Execute(GeneratorExecutionContext context)
|
||||
{
|
||||
GenerateInterfaceStubs(context);
|
||||
}
|
||||
#if !ROSLYN_4
|
||||
|
||||
public void GenerateInterfaceStubs(GeneratorExecutionContext context)
|
||||
public void Execute(GeneratorExecutionContext context)
|
||||
{
|
||||
if (context.SyntaxReceiver is not SyntaxReceiver receiver)
|
||||
return;
|
||||
|
||||
context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.RefitInternalNamespace", out var refitInternalNamespace);
|
||||
|
||||
GenerateInterfaceStubs(
|
||||
context,
|
||||
static (context, diagnostic) => context.ReportDiagnostic(diagnostic),
|
||||
static (context, hintName, sourceText) => context.AddSource(hintName, sourceText),
|
||||
(CSharpCompilation)context.Compilation,
|
||||
refitInternalNamespace,
|
||||
receiver.CandidateMethods.ToImmutableArray(),
|
||||
receiver.CandidateInterfaces.ToImmutableArray());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public void GenerateInterfaceStubs<TContext>(
|
||||
TContext context,
|
||||
Action<TContext, Diagnostic> reportDiagnostic,
|
||||
Action<TContext, string, SourceText> addSource,
|
||||
CSharpCompilation compilation,
|
||||
string? refitInternalNamespace,
|
||||
ImmutableArray<MethodDeclarationSyntax> candidateMethods,
|
||||
ImmutableArray<InterfaceDeclarationSyntax> candidateInterfaces)
|
||||
{
|
||||
refitInternalNamespace = $"{refitInternalNamespace ?? string.Empty}RefitInternalGenerated";
|
||||
|
||||
// we're going to create a new compilation that contains the attribute.
|
||||
// TODO: we should allow source generators to provide source during initialize, so that this step isn't required.
|
||||
var options = (context.Compilation as CSharpCompilation)!.SyntaxTrees[0].Options as CSharpParseOptions;
|
||||
var compilation = context.Compilation;
|
||||
var options = (CSharpParseOptions)compilation.SyntaxTrees[0].Options;
|
||||
|
||||
var disposableInterfaceSymbol = compilation.GetTypeByMetadataName("System.IDisposable")!;
|
||||
var httpMethodBaseAttributeSymbol = compilation.GetTypeByMetadataName("Refit.HttpMethodAttribute");
|
||||
|
||||
if(httpMethodBaseAttributeSymbol == null)
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(RefitNotReferenced, null));
|
||||
reportDiagnostic(context, Diagnostic.Create(RefitNotReferenced, null));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Check the candidates and keep the ones we're actually interested in
|
||||
|
||||
var interfaceToNullableEnabledMap = new Dictionary<INamedTypeSymbol, bool>();
|
||||
#pragma warning disable RS1024 // Compare symbols correctly
|
||||
var interfaceToNullableEnabledMap = new Dictionary<INamedTypeSymbol, bool>(SymbolEqualityComparer.Default);
|
||||
#pragma warning restore RS1024 // Compare symbols correctly
|
||||
var methodSymbols = new List<IMethodSymbol>();
|
||||
foreach (var group in receiver.CandidateMethods.GroupBy(m => m.SyntaxTree))
|
||||
foreach (var group in candidateMethods.GroupBy(m => m.SyntaxTree))
|
||||
{
|
||||
var model = compilation.GetSemanticModel(group.Key);
|
||||
foreach (var method in group)
|
||||
|
@ -79,7 +102,7 @@ namespace Refit.Generator
|
|||
var methodSymbol = model.GetDeclaredSymbol(method);
|
||||
if (IsRefitMethod(methodSymbol, httpMethodBaseAttributeSymbol))
|
||||
{
|
||||
var isAnnotated = context.Compilation.Options.NullableContextOptions == NullableContextOptions.Enable ||
|
||||
var isAnnotated = compilation.Options.NullableContextOptions == NullableContextOptions.Enable ||
|
||||
model.GetNullableContext(method.SpanStart) == NullableContext.Enabled;
|
||||
interfaceToNullableEnabledMap[methodSymbol!.ContainingType] = isAnnotated;
|
||||
|
||||
|
@ -88,12 +111,12 @@ namespace Refit.Generator
|
|||
}
|
||||
}
|
||||
|
||||
var interfaces = methodSymbols.GroupBy(m => m.ContainingType)
|
||||
var interfaces = methodSymbols.GroupBy<IMethodSymbol, INamedTypeSymbol>(m => m.ContainingType, SymbolEqualityComparer.Default)
|
||||
.ToDictionary(g => g.Key, v => v.ToList());
|
||||
|
||||
// Look through the candidate interfaces
|
||||
var interfaceSymbols = new List<INamedTypeSymbol>();
|
||||
foreach(var group in receiver.CandidateInterfaces.GroupBy(i => i.SyntaxTree))
|
||||
foreach(var group in candidateInterfaces.GroupBy(i => i.SyntaxTree))
|
||||
{
|
||||
var model = compilation.GetSemanticModel(group.Key);
|
||||
foreach (var iface in group)
|
||||
|
@ -127,7 +150,7 @@ namespace Refit.Generator
|
|||
if(!interfaces.Any()) return;
|
||||
|
||||
|
||||
var supportsNullable = ((CSharpParseOptions)context.ParseOptions).LanguageVersion >= LanguageVersion.CSharp8;
|
||||
var supportsNullable = options.LanguageVersion >= LanguageVersion.CSharp8;
|
||||
|
||||
var keyCount = new Dictionary<string, int>();
|
||||
|
||||
|
@ -152,10 +175,10 @@ namespace {refitInternalNamespace}
|
|||
";
|
||||
|
||||
|
||||
compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(attributeText, Encoding.UTF8), options));
|
||||
compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(attributeText, Encoding.UTF8), options));
|
||||
|
||||
// add the attribute text
|
||||
context.AddSource("PreserveAttribute.g.cs", SourceText.From(attributeText, Encoding.UTF8));
|
||||
addSource(context, "PreserveAttribute.g.cs", SourceText.From(attributeText, Encoding.UTF8));
|
||||
|
||||
// get the newly bound attribute
|
||||
var preserveAttributeSymbol = compilation.GetTypeByMetadataName($"{refitInternalNamespace}.PreserveAttribute")!;
|
||||
|
@ -177,7 +200,7 @@ namespace Refit.Implementation
|
|||
}}
|
||||
#pragma warning restore
|
||||
";
|
||||
context.AddSource("Generated.g.cs", SourceText.From(generatedClassText, Encoding.UTF8));
|
||||
addSource(context, "Generated.g.cs", SourceText.From(generatedClassText, Encoding.UTF8));
|
||||
|
||||
compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(generatedClassText, Encoding.UTF8), options));
|
||||
|
||||
|
@ -190,14 +213,15 @@ namespace Refit.Implementation
|
|||
// with a refit attribute on them. Types may contain other members, without the attribute, which we'll
|
||||
// need to check for and error out on
|
||||
|
||||
var classSource = ProcessInterface(group.Key,
|
||||
var classSource = ProcessInterface(context,
|
||||
reportDiagnostic,
|
||||
group.Key,
|
||||
group.Value,
|
||||
preserveAttributeSymbol,
|
||||
disposableInterfaceSymbol,
|
||||
httpMethodBaseAttributeSymbol,
|
||||
supportsNullable,
|
||||
interfaceToNullableEnabledMap[group.Key],
|
||||
context);
|
||||
interfaceToNullableEnabledMap[group.Key]);
|
||||
|
||||
var keyName = group.Key.Name;
|
||||
if(keyCount.TryGetValue(keyName, out var value))
|
||||
|
@ -206,19 +230,20 @@ namespace Refit.Implementation
|
|||
}
|
||||
keyCount[keyName] = value;
|
||||
|
||||
context.AddSource($"{keyName}.g.cs", SourceText.From(classSource, Encoding.UTF8));
|
||||
addSource(context, $"{keyName}.g.cs", SourceText.From(classSource, Encoding.UTF8));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string ProcessInterface(INamedTypeSymbol interfaceSymbol,
|
||||
string ProcessInterface<TContext>(TContext context,
|
||||
Action<TContext, Diagnostic> reportDiagnostic,
|
||||
INamedTypeSymbol interfaceSymbol,
|
||||
List<IMethodSymbol> refitMethods,
|
||||
ISymbol preserveAttributeSymbol,
|
||||
ISymbol disposableInterfaceSymbol,
|
||||
INamedTypeSymbol httpMethodBaseAttributeSymbol,
|
||||
bool supportsNullable,
|
||||
bool nullableEnabled,
|
||||
GeneratorExecutionContext context)
|
||||
bool nullableEnabled)
|
||||
{
|
||||
|
||||
// Get the class name with the type parameters, then remove the namespace
|
||||
|
@ -331,7 +356,7 @@ namespace Refit.Implementation
|
|||
!method.IsAbstract) // If an interface method has a body, it won't be abstract
|
||||
continue;
|
||||
|
||||
ProcessNonRefitMethod(source, method, context);
|
||||
ProcessNonRefitMethod(context, reportDiagnostic, source, method);
|
||||
}
|
||||
|
||||
// Handle Dispose
|
||||
|
@ -458,7 +483,7 @@ namespace Refit.Implementation
|
|||
|
||||
}
|
||||
|
||||
void ProcessNonRefitMethod(StringBuilder source, IMethodSymbol methodSymbol, GeneratorExecutionContext context)
|
||||
void ProcessNonRefitMethod<TContext>(TContext context, Action<TContext, Diagnostic> reportDiagnostic, StringBuilder source, IMethodSymbol methodSymbol)
|
||||
{
|
||||
WriteMethodOpening(source, methodSymbol, true);
|
||||
|
||||
|
@ -471,7 +496,7 @@ namespace Refit.Implementation
|
|||
foreach(var location in methodSymbol.Locations)
|
||||
{
|
||||
var diagnostic = Diagnostic.Create(InvalidRefitMember, location, methodSymbol.ContainingType.Name, methodSymbol.Name);
|
||||
context.ReportDiagnostic(diagnostic);
|
||||
reportDiagnostic(context, diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -515,6 +540,48 @@ namespace Refit.Implementation
|
|||
return methodSymbol?.GetAttributes().Any(ad => ad.AttributeClass?.InheritsFromOrEquals(httpMethodAttibute) == true) == true;
|
||||
}
|
||||
|
||||
#if ROSLYN_4
|
||||
|
||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||
{
|
||||
// We're looking for methods with an attribute that are in an interface
|
||||
var candidateMethodsProvider = context.SyntaxProvider.CreateSyntaxProvider(
|
||||
(syntax, cancellationToken) => syntax is MethodDeclarationSyntax { Parent: InterfaceDeclarationSyntax, AttributeLists: { Count: > 0 } },
|
||||
(context, cancellationToken) => (MethodDeclarationSyntax)context.Node);
|
||||
|
||||
// We also look for interfaces that derive from others, so we can see if any base methods contain
|
||||
// Refit methods
|
||||
var candidateInterfacesProvider = context.SyntaxProvider.CreateSyntaxProvider(
|
||||
(syntax, cancellationToken) => syntax is InterfaceDeclarationSyntax { BaseList: not null },
|
||||
(context, cancellationToken) => (InterfaceDeclarationSyntax)context.Node);
|
||||
|
||||
var refitInternalNamespace = context.AnalyzerConfigOptionsProvider.Select(
|
||||
(analyzerConfigOptionsProvider, cancellationToken) => analyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.RefitInternalNamespace", out var refitInternalNamespace) ? refitInternalNamespace : null);
|
||||
|
||||
var inputs = candidateMethodsProvider.Collect()
|
||||
.Combine(candidateInterfacesProvider.Collect())
|
||||
.Select((combined, cancellationToken) => (candidateMethods: combined.Left, candidateInterfaces: combined.Right))
|
||||
.Combine(refitInternalNamespace)
|
||||
.Combine(context.CompilationProvider)
|
||||
.Select((combined, cancellationToken) => (combined.Left.Left.candidateMethods, combined.Left.Left.candidateInterfaces, refitInternalNamespace: combined.Left.Right, compilation: combined.Right));
|
||||
|
||||
context.RegisterSourceOutput(
|
||||
inputs,
|
||||
(context, collectedValues) =>
|
||||
{
|
||||
GenerateInterfaceStubs(
|
||||
context,
|
||||
static (context, diagnostic) => context.ReportDiagnostic(diagnostic),
|
||||
static (context, hintName, sourceText) => context.AddSource(hintName, sourceText),
|
||||
(CSharpCompilation)collectedValues.compilation,
|
||||
collectedValues.refitInternalNamespace,
|
||||
collectedValues.candidateMethods,
|
||||
collectedValues.candidateInterfaces);
|
||||
});
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
public void Initialize(GeneratorInitializationContext context)
|
||||
{
|
||||
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
|
||||
|
@ -544,5 +611,7 @@ namespace Refit.Implementation
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ using Xunit;
|
|||
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
using VerifyCS = Refit.Tests.CSharpSourceGeneratorVerifier<Refit.Generator.InterfaceStubGenerator>;
|
||||
using VerifyCSV2 = Refit.Tests.CSharpIncrementalSourceGeneratorVerifier<Refit.Generator.InterfaceStubGeneratorV2>;
|
||||
|
||||
namespace Refit.Tests
|
||||
{
|
||||
|
@ -102,6 +103,7 @@ namespace Refit.Tests
|
|||
public async Task NoRefitInterfacesSmokeTest()
|
||||
{
|
||||
var input = File.ReadAllText(IntegrationTestHelper.GetPath("IInterfaceWithoutRefit.cs"));
|
||||
|
||||
await new VerifyCS.Test
|
||||
{
|
||||
ReferenceAssemblies = ReferenceAssemblies,
|
||||
|
@ -111,6 +113,16 @@ namespace Refit.Tests
|
|||
Sources = { input },
|
||||
},
|
||||
}.RunAsync();
|
||||
|
||||
await new VerifyCSV2.Test
|
||||
{
|
||||
ReferenceAssemblies = ReferenceAssemblies,
|
||||
TestState =
|
||||
{
|
||||
AdditionalReferences = { RefitAssembly },
|
||||
Sources = { input },
|
||||
},
|
||||
}.RunAsync();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -640,6 +652,24 @@ namespace Refit.Implementation
|
|||
},
|
||||
},
|
||||
}.RunAsync();
|
||||
|
||||
await new VerifyCSV2.Test
|
||||
{
|
||||
ReferenceAssemblies = ReferenceAssemblies,
|
||||
TestState =
|
||||
{
|
||||
AdditionalReferences = { RefitAssembly },
|
||||
Sources = { input },
|
||||
GeneratedSources =
|
||||
{
|
||||
(typeof(InterfaceStubGeneratorV2), "PreserveAttribute.g.cs", output1),
|
||||
(typeof(InterfaceStubGeneratorV2), "Generated.g.cs", output1_5),
|
||||
(typeof(InterfaceStubGeneratorV2), "IGitHubApi.g.cs", output2),
|
||||
(typeof(InterfaceStubGeneratorV2), "IGitHubApiDisposable.g.cs", output3),
|
||||
(typeof(InterfaceStubGeneratorV2), "INestedGitHubApi.g.cs", output4),
|
||||
},
|
||||
},
|
||||
}.RunAsync();
|
||||
}
|
||||
|
||||
|
||||
|
@ -768,6 +798,22 @@ namespace Refit.Implementation
|
|||
},
|
||||
},
|
||||
}.RunAsync();
|
||||
|
||||
await new VerifyCSV2.Test
|
||||
{
|
||||
ReferenceAssemblies = ReferenceAssemblies,
|
||||
TestState =
|
||||
{
|
||||
AdditionalReferences = { RefitAssembly },
|
||||
Sources = { input },
|
||||
GeneratedSources =
|
||||
{
|
||||
(typeof(InterfaceStubGeneratorV2), "PreserveAttribute.g.cs", output1),
|
||||
(typeof(InterfaceStubGeneratorV2), "Generated.g.cs", output1_5),
|
||||
(typeof(InterfaceStubGeneratorV2), "IServiceWithoutNamespace.g.cs", output2),
|
||||
},
|
||||
},
|
||||
}.RunAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.0.0-2.final" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing.XUnit" Version="1.1.0" />
|
||||
<PackageReference Include="RichardSzalay.MockHttp" Version="6.0.0" />
|
||||
<ProjectReference Include="..\Refit.HttpClientFactory\Refit.HttpClientFactory.csproj" />
|
||||
<ProjectReference Include="..\Refit.Newtonsoft.Json\Refit.Newtonsoft.Json.csproj" />
|
||||
<ProjectReference Include="..\InterfaceStubGenerator.Core\InterfaceStubGenerator.Core.csproj"
|
||||
<ProjectReference Include="..\InterfaceStubGenerator.Roslyn38\InterfaceStubGenerator.Roslyn38.csproj"
|
||||
OutputItemType="Analyzer" ReferenceOutputAssembly="true" />
|
||||
<ProjectReference Include="..\InterfaceStubGenerator.Roslyn40\InterfaceStubGenerator.Roslyn40.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net461' ">
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Testing;
|
||||
using Microsoft.CodeAnalysis.Testing;
|
||||
using Microsoft.CodeAnalysis.Testing.Verifiers;
|
||||
|
||||
namespace Refit.Tests
|
||||
{
|
||||
public static partial class CSharpIncrementalSourceGeneratorVerifier<TIncrementalGenerator>
|
||||
where TIncrementalGenerator : IIncrementalGenerator, new()
|
||||
{
|
||||
public class Test : CSharpSourceGeneratorTest<EmptySourceGeneratorProvider, XUnitVerifier>
|
||||
{
|
||||
public Test()
|
||||
{
|
||||
SolutionTransforms.Add((solution, projectId) =>
|
||||
{
|
||||
var compilationOptions = solution.GetProject(projectId).CompilationOptions;
|
||||
compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(
|
||||
compilationOptions.SpecificDiagnosticOptions.SetItems(CSharpVerifierHelper.NullableWarnings));
|
||||
solution = solution.WithProjectCompilationOptions(projectId, compilationOptions);
|
||||
|
||||
return solution;
|
||||
});
|
||||
}
|
||||
|
||||
protected override IEnumerable<ISourceGenerator> GetSourceGenerators()
|
||||
{
|
||||
yield return new TIncrementalGenerator().AsSourceGenerator();
|
||||
}
|
||||
|
||||
protected override ParseOptions CreateParseOptions()
|
||||
{
|
||||
var parseOptions = (CSharpParseOptions)base.CreateParseOptions();
|
||||
return parseOptions.WithLanguageVersion(LanguageVersion.Preview);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Refit.Tests
|
||||
{
|
||||
public static partial class CSharpIncrementalSourceGeneratorVerifier<TIncrementalGenerator>
|
||||
where TIncrementalGenerator : IIncrementalGenerator, new()
|
||||
{
|
||||
}
|
||||
}
|
27
Refit.sln
27
Refit.sln
|
@ -23,9 +23,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Refit.HttpClientFactory", "
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Refit.Newtonsoft.Json", "Refit.Newtonsoft.Json\Refit.Newtonsoft.Json.csproj", "{2210E606-1C91-4EA0-8876-3B2F501F2669}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InterfaceStubGenerator.Core", "InterfaceStubGenerator.Core\InterfaceStubGenerator.Core.csproj", "{72869789-0310-4916-9A41-20D16A01C1B8}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InterfaceStubGenerator.Roslyn38", "InterfaceStubGenerator.Roslyn38\InterfaceStubGenerator.Roslyn38.csproj", "{72869789-0310-4916-9A41-20D16A01C1B8}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "InterfaceStubGenerator.Shared", "InterfaceStubGenerator.Shared\InterfaceStubGenerator.Shared.shproj", "{B591423D-F92D-4E00-B0EB-615C9853506C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InterfaceStubGenerator.Roslyn40", "InterfaceStubGenerator.Roslyn40\InterfaceStubGenerator.Roslyn40.csproj", "{A4B61169-3314-41DB-8156-BE9677C90C9F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
InterfaceStubGenerator.Shared\InterfaceStubGenerator.Shared.projitems*{72869789-0310-4916-9a41-20d16a01c1b8}*SharedItemsImports = 5
|
||||
InterfaceStubGenerator.Shared\InterfaceStubGenerator.Shared.projitems*{a4b61169-3314-41db-8156-be9677c90c9f}*SharedItemsImports = 5
|
||||
InterfaceStubGenerator.Shared\InterfaceStubGenerator.Shared.projitems*{b591423d-f92d-4e00-b0eb-615c9853506c}*SharedItemsImports = 13
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
|
@ -117,6 +126,22 @@ Global
|
|||
{72869789-0310-4916-9A41-20D16A01C1B8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{72869789-0310-4916-9A41-20D16A01C1B8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{72869789-0310-4916-9A41-20D16A01C1B8}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A4B61169-3314-41DB-8156-BE9677C90C9F}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
|
||||
<Reference Include="System.Web" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
<ProjectReference Include="..\InterfaceStubGenerator.Core\InterfaceStubGenerator.Core.csproj" ReferenceOutputAssembly="false" />
|
||||
<ProjectReference Include="..\InterfaceStubGenerator.Roslyn38\InterfaceStubGenerator.Roslyn38.csproj" ReferenceOutputAssembly="false" />
|
||||
<ProjectReference Include="..\InterfaceStubGenerator.Roslyn40\InterfaceStubGenerator.Roslyn40.csproj" ReferenceOutputAssembly="false" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Label="Package">
|
||||
|
@ -25,9 +26,14 @@
|
|||
|
||||
<!-- We need this one to catch older clients -->
|
||||
<None Include="targets\refit.targets" PackagePath="build\netstandard2.0" Pack="true" />
|
||||
|
||||
<None Include="..\InterfaceStubGenerator.Core\bin\$(Configuration)\netstandard2.0\InterfaceStubGenerator.Core.dll"
|
||||
PackagePath="analyzers\cs\"
|
||||
|
||||
<None Include="..\InterfaceStubGenerator.Roslyn38\bin\$(Configuration)\netstandard2.0\InterfaceStubGeneratorV1.dll"
|
||||
PackagePath="analyzers\cs\roslyn38"
|
||||
Pack="true"
|
||||
Visible="false" />
|
||||
|
||||
<None Include="..\InterfaceStubGenerator.Roslyn40\bin\$(Configuration)\netstandard2.0\InterfaceStubGeneratorV2.dll"
|
||||
PackagePath="analyzers\cs\roslyn40"
|
||||
Pack="true"
|
||||
Visible="false" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -4,4 +4,17 @@
|
|||
<CompilerVisibleProperty Include="RefitInternalNamespace" />
|
||||
</ItemGroup>
|
||||
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' >= '17.0' AND '$(DesignTimeBuild)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Analyzer Include="$(MSBuildThisFileDirectory)../../analyzers/cs/roslyn40/*.dll" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Analyzer Include="$(MSBuildThisFileDirectory)../../analyzers/cs/roslyn38/*.dll" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
|
||||
</Project>
|
||||
|
|
Загрузка…
Ссылка в новой задаче