diff --git a/InterfaceStubGenerator.Core/InterfaceStubGenerator.Core.csproj b/InterfaceStubGenerator.Roslyn38/InterfaceStubGenerator.Roslyn38.csproj similarity index 83% rename from InterfaceStubGenerator.Core/InterfaceStubGenerator.Core.csproj rename to InterfaceStubGenerator.Roslyn38/InterfaceStubGenerator.Roslyn38.csproj index 68c931c4f..6e9ca887a 100644 --- a/InterfaceStubGenerator.Core/InterfaceStubGenerator.Core.csproj +++ b/InterfaceStubGenerator.Roslyn38/InterfaceStubGenerator.Roslyn38.csproj @@ -2,6 +2,7 @@ netstandard2.0 + InterfaceStubGeneratorV1 Refit.Generator false ..\buildtask.snk @@ -21,4 +22,6 @@ + + diff --git a/InterfaceStubGenerator.Roslyn40/InterfaceStubGenerator.Roslyn40.csproj b/InterfaceStubGenerator.Roslyn40/InterfaceStubGenerator.Roslyn40.csproj new file mode 100644 index 000000000..4a8cded8d --- /dev/null +++ b/InterfaceStubGenerator.Roslyn40/InterfaceStubGenerator.Roslyn40.csproj @@ -0,0 +1,28 @@ + + + + netstandard2.0 + InterfaceStubGeneratorV2 + Refit.Generator + false + ..\buildtask.snk + true + true + enable + $(DefineConstants);ROSLYN_4 + + + + + + + + + $(BuildVersion) + $(BuildVersionSimple) + + + + + + diff --git a/InterfaceStubGenerator.Core/ITypeSymbolExtensions.cs b/InterfaceStubGenerator.Shared/ITypeSymbolExtensions.cs similarity index 100% rename from InterfaceStubGenerator.Core/ITypeSymbolExtensions.cs rename to InterfaceStubGenerator.Shared/ITypeSymbolExtensions.cs diff --git a/InterfaceStubGenerator.Shared/InterfaceStubGenerator.Shared.projitems b/InterfaceStubGenerator.Shared/InterfaceStubGenerator.Shared.projitems new file mode 100644 index 000000000..5589f69c2 --- /dev/null +++ b/InterfaceStubGenerator.Shared/InterfaceStubGenerator.Shared.projitems @@ -0,0 +1,15 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + b591423d-f92d-4e00-b0eb-615c9853506c + + + InterfaceStubGenerator.Shared + + + + + + \ No newline at end of file diff --git a/InterfaceStubGenerator.Shared/InterfaceStubGenerator.Shared.shproj b/InterfaceStubGenerator.Shared/InterfaceStubGenerator.Shared.shproj new file mode 100644 index 000000000..fa970afbf --- /dev/null +++ b/InterfaceStubGenerator.Shared/InterfaceStubGenerator.Shared.shproj @@ -0,0 +1,13 @@ + + + + b591423d-f92d-4e00-b0eb-615c9853506c + 14.0 + + + + + + + + diff --git a/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs b/InterfaceStubGenerator.Shared/InterfaceStubGenerator.cs similarity index 79% rename from InterfaceStubGenerator.Core/InterfaceStubGenerator.cs rename to InterfaceStubGenerator.Shared/InterfaceStubGenerator.cs index 1ca673cdb..e59526513 100644 --- a/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs +++ b/InterfaceStubGenerator.Shared/InterfaceStubGenerator.cs @@ -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 @@ public class InterfaceStubGenerator : ISourceGenerator 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 context, + Action reportDiagnostic, + Action addSource, + CSharpCompilation compilation, + string? refitInternalNamespace, + ImmutableArray candidateMethods, + ImmutableArray 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(); +#pragma warning disable RS1024 // Compare symbols correctly + var interfaceToNullableEnabledMap = new Dictionary(SymbolEqualityComparer.Default); +#pragma warning restore RS1024 // Compare symbols correctly var methodSymbols = new List(); - 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 @@ public void GenerateInterfaceStubs(GeneratorExecutionContext context) 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 @@ public void GenerateInterfaceStubs(GeneratorExecutionContext context) } } - var interfaces = methodSymbols.GroupBy(m => m.ContainingType) + var interfaces = methodSymbols.GroupBy(m => m.ContainingType, SymbolEqualityComparer.Default) .ToDictionary(g => g.Key, v => v.ToList()); // Look through the candidate interfaces var interfaceSymbols = new List(); - 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 @@ public void GenerateInterfaceStubs(GeneratorExecutionContext context) if(!interfaces.Any()) return; - var supportsNullable = ((CSharpParseOptions)context.ParseOptions).LanguageVersion >= LanguageVersion.CSharp8; + var supportsNullable = options.LanguageVersion >= LanguageVersion.CSharp8; var keyCount = new Dictionary(); @@ -152,10 +175,10 @@ sealed class PreserveAttribute : global::System.Attribute "; - 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 @@ internal static partial class Generated }} #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 @@ internal static partial class Generated // 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 @@ internal static partial class Generated } 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 context, + Action reportDiagnostic, + INamedTypeSymbol interfaceSymbol, List 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 @@ partial class {ns}{classDeclaration} !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 @@ void WriteConstraitsForTypeParameter(StringBuilder source, ITypeParameterSymbol } - void ProcessNonRefitMethod(StringBuilder source, IMethodSymbol methodSymbol, GeneratorExecutionContext context) + void ProcessNonRefitMethod(TContext context, Action reportDiagnostic, StringBuilder source, IMethodSymbol methodSymbol) { WriteMethodOpening(source, methodSymbol, true); @@ -471,7 +496,7 @@ void ProcessNonRefitMethod(StringBuilder source, IMethodSymbol methodSymbol, Gen 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 @@ bool IsRefitMethod(IMethodSymbol? methodSymbol, INamedTypeSymbol httpMethodAttib 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 @@ methodDeclarationSyntax.Parent is InterfaceDeclarationSyntax && } } } + +#endif } } diff --git a/Refit.Tests/InterfaceStubGenerator.cs b/Refit.Tests/InterfaceStubGenerator.cs index 09df22413..adfc35bfb 100644 --- a/Refit.Tests/InterfaceStubGenerator.cs +++ b/Refit.Tests/InterfaceStubGenerator.cs @@ -16,6 +16,7 @@ using Task = System.Threading.Tasks.Task; using VerifyCS = Refit.Tests.CSharpSourceGeneratorVerifier; +using VerifyCSV2 = Refit.Tests.CSharpIncrementalSourceGeneratorVerifier; namespace Refit.Tests { @@ -102,6 +103,7 @@ static Compilation CreateCompilation(params string[] sourceFiles) public async Task NoRefitInterfacesSmokeTest() { var input = File.ReadAllText(IntegrationTestHelper.GetPath("IInterfaceWithoutRefit.cs")); + await new VerifyCS.Test { ReferenceAssemblies = ReferenceAssemblies, @@ -111,6 +113,16 @@ public async Task NoRefitInterfacesSmokeTest() Sources = { input }, }, }.RunAsync(); + + await new VerifyCSV2.Test + { + ReferenceAssemblies = ReferenceAssemblies, + TestState = + { + AdditionalReferences = { RefitAssembly }, + Sources = { input }, + }, + }.RunAsync(); } [Fact] @@ -640,6 +652,24 @@ public RefitTestsTestNestedINestedGitHubApi(global::System.Net.Http.HttpClient c }, }, }.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 @@ public IServiceWithoutNamespace(global::System.Net.Http.HttpClient client, globa }, }, }.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(); } } diff --git a/Refit.Tests/Refit.Tests.csproj b/Refit.Tests/Refit.Tests.csproj index dd6e29c49..e5a9df7e9 100644 --- a/Refit.Tests/Refit.Tests.csproj +++ b/Refit.Tests/Refit.Tests.csproj @@ -18,13 +18,14 @@ - + - + diff --git a/Refit.Tests/Verifiers/CSharpIncrementalSourceGeneratorVerifier`1+Test.cs b/Refit.Tests/Verifiers/CSharpIncrementalSourceGeneratorVerifier`1+Test.cs new file mode 100644 index 000000000..c310c1295 --- /dev/null +++ b/Refit.Tests/Verifiers/CSharpIncrementalSourceGeneratorVerifier`1+Test.cs @@ -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 + where TIncrementalGenerator : IIncrementalGenerator, new() + { + public class Test : CSharpSourceGeneratorTest + { + 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 GetSourceGenerators() + { + yield return new TIncrementalGenerator().AsSourceGenerator(); + } + + protected override ParseOptions CreateParseOptions() + { + var parseOptions = (CSharpParseOptions)base.CreateParseOptions(); + return parseOptions.WithLanguageVersion(LanguageVersion.Preview); + } + } + } +} diff --git a/Refit.Tests/Verifiers/CSharpIncrementalSourceGeneratorVerifier`1.cs b/Refit.Tests/Verifiers/CSharpIncrementalSourceGeneratorVerifier`1.cs new file mode 100644 index 000000000..9aa951242 --- /dev/null +++ b/Refit.Tests/Verifiers/CSharpIncrementalSourceGeneratorVerifier`1.cs @@ -0,0 +1,9 @@ +using Microsoft.CodeAnalysis; + +namespace Refit.Tests +{ + public static partial class CSharpIncrementalSourceGeneratorVerifier + where TIncrementalGenerator : IIncrementalGenerator, new() + { + } +} diff --git a/Refit.sln b/Refit.sln index 7776f0ce8..b275022a3 100644 --- a/Refit.sln +++ b/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 diff --git a/Refit/Refit.csproj b/Refit/Refit.csproj index a1f7efaa7..f55fd7131 100644 --- a/Refit/Refit.csproj +++ b/Refit/Refit.csproj @@ -16,7 +16,8 @@ - + + @@ -25,9 +26,14 @@ - - + + diff --git a/Refit/targets/refit.props b/Refit/targets/refit.props index c5eee5805..33c3801b7 100644 --- a/Refit/targets/refit.props +++ b/Refit/targets/refit.props @@ -4,4 +4,17 @@ + + + + + + + + + + + + +