Merge pull request #1216 from sharwell/multi-target

Support Roslyn 3.8 and Roslyn 4.0 source generator scenarios
This commit is contained in:
Claire Novotny 2021-08-19 07:53:52 -04:00 коммит произвёл GitHub
Родитель 1a3890d893 482cf42036
Коммит 150dd1f450
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 304 добавлений и 35 удалений

Просмотреть файл

@ -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)' &lt; '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()
{
}
}

Просмотреть файл

@ -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>