mirror of
https://github.com/FabInfra/capnproto-dotnetcore_Runtime.git
synced 2025-03-12 06:41:50 +01:00
Initial skeleton for MSBuild integration
This commit is contained in:
parent
dbe6c29f8b
commit
bf34494ae1
@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime.Tests.Cor
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "capnpc-csharp.tests", "capnpc-csharp.tests\capnpc-csharp.tests.csproj", "{B77AC567-E232-4072-85C3-8689566BF3D4}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "capnpc-csharp.tests", "capnpc-csharp.tests\capnpc-csharp.tests.csproj", "{B77AC567-E232-4072-85C3-8689566BF3D4}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnpc.Csharp.MsBuild.Generation", "Capnpc.Csharp.MsBuild.Generation\Capnpc.Csharp.MsBuild.Generation.csproj", "{1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -39,6 +41,10 @@ Global
|
|||||||
{B77AC567-E232-4072-85C3-8689566BF3D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B77AC567-E232-4072-85C3-8689566BF3D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{B77AC567-E232-4072-85C3-8689566BF3D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B77AC567-E232-4072-85C3-8689566BF3D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B77AC567-E232-4072-85C3-8689566BF3D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B77AC567-E232-4072-85C3-8689566BF3D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
4
Capnpc.Csharp.MsBuild.Generation/AssemblyAttributes.cs
Normal file
4
Capnpc.Csharp.MsBuild.Generation/AssemblyAttributes.cs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Security;
|
||||||
|
|
@ -0,0 +1,79 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>netstandard2.0;netcoreapp2.1</TargetFrameworks>
|
||||||
|
<SignAssembly>false</SignAssembly>
|
||||||
|
<NuspecFile>$(MSBuildThisFileDirectory)Capnpc.Csharp.MsBuild.Generation.nuspec</NuspecFile>
|
||||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
|
||||||
|
|
||||||
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
<NoPackageAnalysis>true</NoPackageAnalysis>
|
||||||
|
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||||
|
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Composition" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.SDK" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.SDK.Tools" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Threading" />
|
||||||
|
<PackageReference Include="System.Collections.Immutable" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<PackageReference>
|
||||||
|
<PrivateAssets>All</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Build.Framework" Version="15.8.166" />
|
||||||
|
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.8.166" />
|
||||||
|
<PackageReference Update="@(PackageReference)" PrivateAssets="All" />
|
||||||
|
<PackageReference Update="Microsoft.VisualStudio.Composition" Version="15.8.98" />
|
||||||
|
<PackageReference Update="Microsoft.VisualStudio.ProjectSystem" Version="15.8.243" />
|
||||||
|
<PackageReference Update="Microsoft.VisualStudio.ProjectSystem.SDK" Version="15.8.243" />
|
||||||
|
<PackageReference Update="Microsoft.VisualStudio.ProjectSystem.SDK.Tools" Version="15.8.243" />
|
||||||
|
<PackageReference Update="Microsoft.VisualStudio.Threading" Version="15.8.132" />
|
||||||
|
<PackageReference Update="System.Collections.Immutable" Version="1.5.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="FrameworkDependent\**\*.cs" />
|
||||||
|
<Compile Include="FrameworkDependent\*.cs" />
|
||||||
|
<None Include="FrameworkDependent\**\*.cs" />
|
||||||
|
<Compile Include="FrameworkDependent\FullFramework\**\*.cs" Condition="'$(TargetFramework)' == '$(CapnpcCsharp_FullFramework_Tools_TFM)'" />
|
||||||
|
<Compile Include="FrameworkDependent\DotNetCore\**\*.cs" Condition="'$(TargetFramework)' == '$(CapnpcCsharp_Core_Tools_TFM)'" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="FrameworkDependent\DotNetCore\" />
|
||||||
|
<Folder Include="FrameworkDependent\FullFramework\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.Build">
|
||||||
|
<HintPath>Microsoft.Build</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.Build.Framework">
|
||||||
|
<HintPath>Microsoft.Build.Framework</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.Build.Utilities.Core">
|
||||||
|
<HintPath>Microsoft.Build.Utilities.Core</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.ComponentModel.Composition" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="build\CPS\Buildsystem\Rules\FeatureFileType.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</None>
|
||||||
|
<None Update="build\CPS\Buildsystem\Rules\ProjectItemsSchema.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>Capnpc.Csharp.Generation</id>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<title>Capnpc.Csharp.MsBuild.Generation</title>
|
||||||
|
<authors>Christian Köllner and contributors</authors>
|
||||||
|
<owners>Christian Köllner</owners>
|
||||||
|
<description>Package to enable the .capnp -> .cs file generation during build time</description>
|
||||||
|
<summary>Package to enable the .capnp -> .cs file generation during build time</summary>
|
||||||
|
<language>en-US</language>
|
||||||
|
<projectUrl>https://github.com/c80k/capnproto-dotnetcore</projectUrl>
|
||||||
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
|
<license type="expression">MIT</license>
|
||||||
|
<tags>capnproto csharp msbuild</tags>
|
||||||
|
<copyright>Christian Köllner and contributors</copyright>
|
||||||
|
<dependencies>
|
||||||
|
</dependencies>
|
||||||
|
</metadata>
|
||||||
|
<files>
|
||||||
|
<file src="build\**\*" target="build" />
|
||||||
|
<file src="buildMultiTargeting\**\*" target="buildMultiTargeting" />
|
||||||
|
<file src="bin\Release\netstandard2.0\*.dll" target="tasks\netstandard2.0" />
|
||||||
|
<file src="bin\Release\netcoreapp2.1\*.dll" target="tasks\netcoreapp2.1" />
|
||||||
|
<file src="bin\Release\netcoreapp2.1\*.deps.json" target="tasks\netcoreapp2.1" />
|
||||||
|
|
||||||
|
<file src="..\Licenses\**\*" target="licenses" />
|
||||||
|
<file src="..\LICENSE" target="LICENSE" />
|
||||||
|
</files>
|
||||||
|
</package>
|
49
Capnpc.Csharp.MsBuild.Generation/CodeBehindWriter.cs
Normal file
49
Capnpc.Csharp.MsBuild.Generation/CodeBehindWriter.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public class CodeBehindWriter
|
||||||
|
{
|
||||||
|
public CodeBehindWriter(TaskLoggingHelper log)
|
||||||
|
{
|
||||||
|
Log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskLoggingHelper Log { get; }
|
||||||
|
|
||||||
|
public string WriteCodeBehindFile(string outputPath, string featureFile, TestFileGeneratorResult testFileGeneratorResult) //todo needs unit tests
|
||||||
|
{
|
||||||
|
//if (string.IsNullOrEmpty(testFileGeneratorResult.Filename))
|
||||||
|
//{
|
||||||
|
// Log?.LogWithNameTag(Log.LogError, $"{featureFile} has no generated filename");
|
||||||
|
// return null;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//string directoryPath = Path.GetDirectoryName(outputPath) ?? throw new InvalidOperationException();
|
||||||
|
//Log?.LogWithNameTag(Log.LogMessage, directoryPath);
|
||||||
|
|
||||||
|
//Log?.LogWithNameTag(Log.LogMessage, $"Writing data to {outputPath}; path = {directoryPath}; generatedFilename = {testFileGeneratorResult.Filename}");
|
||||||
|
|
||||||
|
//if (File.Exists(outputPath))
|
||||||
|
//{
|
||||||
|
// if (!FileSystemHelper.FileCompareContent(outputPath, testFileGeneratorResult.GeneratedTestCode))
|
||||||
|
// {
|
||||||
|
// File.WriteAllText(outputPath, testFileGeneratorResult.GeneratedTestCode);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// if (!Directory.Exists(directoryPath))
|
||||||
|
// {
|
||||||
|
// Directory.CreateDirectory(directoryPath);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// File.WriteAllText(outputPath, testFileGeneratorResult.GeneratedTestCode);
|
||||||
|
//}
|
||||||
|
|
||||||
|
return outputPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public class FeatureCodeBehindGenerator : IDisposable
|
||||||
|
{
|
||||||
|
//private SpecFlowProject _specFlowProject;
|
||||||
|
//private ITestGenerator _testGenerator;
|
||||||
|
|
||||||
|
public void InitializeProject(string projectPath, string rootNamespace, IEnumerable<string> generatorPlugins)
|
||||||
|
{
|
||||||
|
//_specFlowProject = MsBuildProjectReader.LoadSpecFlowProjectFromMsBuild(Path.GetFullPath(projectPath), rootNamespace);
|
||||||
|
|
||||||
|
//var projectSettings = _specFlowProject.ProjectSettings;
|
||||||
|
|
||||||
|
//var testGeneratorFactory = new TestGeneratorFactory();
|
||||||
|
|
||||||
|
//_testGenerator = testGeneratorFactory.CreateGenerator(projectSettings, generatorPlugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public TestFileGeneratorResult GenerateCodeBehindFile(string featureFile)
|
||||||
|
{
|
||||||
|
//var featureFileInput = new FeatureFileInput(featureFile);
|
||||||
|
//var generatedFeatureFileName = Path.GetFileName(_testGenerator.GetTestFullPath(featureFileInput));
|
||||||
|
|
||||||
|
//var testGeneratorResult = _testGenerator.GenerateTestFile(featureFileInput, new GenerationSettings());
|
||||||
|
|
||||||
|
return new TestFileGeneratorResult(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
//_testGenerator?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public class FeatureFileCodeBehindGenerator : ICapnpCsharpGenerator
|
||||||
|
{
|
||||||
|
private readonly FilePathGenerator _filePathGenerator;
|
||||||
|
|
||||||
|
public FeatureFileCodeBehindGenerator(TaskLoggingHelper log)
|
||||||
|
{
|
||||||
|
Log = log ?? throw new ArgumentNullException(nameof(log));
|
||||||
|
_filePathGenerator = new FilePathGenerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskLoggingHelper Log { get; }
|
||||||
|
|
||||||
|
public IEnumerable<string> GenerateFilesForProject(
|
||||||
|
string projectPath,
|
||||||
|
string rootNamespace,
|
||||||
|
List<string> CapnpFiles,
|
||||||
|
List<string> generatorPlugins,
|
||||||
|
string projectFolder,
|
||||||
|
string outputPath)
|
||||||
|
{
|
||||||
|
using (var featureCodeBehindGenerator = new FeatureCodeBehindGenerator())
|
||||||
|
{
|
||||||
|
featureCodeBehindGenerator.InitializeProject(projectPath, rootNamespace, generatorPlugins);
|
||||||
|
|
||||||
|
var codeBehindWriter = new CodeBehindWriter(null);
|
||||||
|
|
||||||
|
if (CapnpFiles == null)
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var featureFile in CapnpFiles)
|
||||||
|
{
|
||||||
|
var featureFileItemSpec = featureFile;
|
||||||
|
var generatorResult = featureCodeBehindGenerator.GenerateCodeBehindFile(featureFileItemSpec);
|
||||||
|
|
||||||
|
if (!generatorResult.Success)
|
||||||
|
{
|
||||||
|
foreach (var error in generatorResult.Errors)
|
||||||
|
{
|
||||||
|
//Log.LogError(
|
||||||
|
// null,
|
||||||
|
// null,
|
||||||
|
// null,
|
||||||
|
// featureFile,
|
||||||
|
// error.Line,
|
||||||
|
// error.LinePosition,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// error.Message);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetFilePath = _filePathGenerator.GenerateFilePath(
|
||||||
|
projectFolder,
|
||||||
|
outputPath,
|
||||||
|
featureFile,
|
||||||
|
generatorResult.Filename);
|
||||||
|
|
||||||
|
var resultedFile = codeBehindWriter.WriteCodeBehindFile(targetFilePath, featureFile, generatorResult);
|
||||||
|
|
||||||
|
yield return FileSystemHelper.GetRelativePath(resultedFile, projectFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
Capnpc.Csharp.MsBuild.Generation/FilePathGenerator.cs
Normal file
31
Capnpc.Csharp.MsBuild.Generation/FilePathGenerator.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public class FilePathGenerator
|
||||||
|
{
|
||||||
|
public string GenerateFilePath(string projectFolder, string relativeOutputPath, string featureFileName, string generatedCodeBehindFileName)
|
||||||
|
{
|
||||||
|
if (projectFolder is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(projectFolder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFileName is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(featureFileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generatedCodeBehindFileName is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(generatedCodeBehindFileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
string featureFileFullPath = Path.GetFullPath(Path.Combine(projectFolder, relativeOutputPath ?? "", featureFileName));
|
||||||
|
string featureFileDirPath = Path.GetDirectoryName(featureFileFullPath);
|
||||||
|
|
||||||
|
return Path.Combine(featureFileDirPath, generatedCodeBehindFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
204
Capnpc.Csharp.MsBuild.Generation/FileSystemHelper.cs
Normal file
204
Capnpc.Csharp.MsBuild.Generation/FileSystemHelper.cs
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public static class FileSystemHelper
|
||||||
|
{
|
||||||
|
public static void CopyFileToFolder(string filePath, string folderName)
|
||||||
|
{
|
||||||
|
File.Copy(filePath, Path.Combine(folderName, Path.GetFileName(filePath)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetRelativePath(string path, string basePath)
|
||||||
|
{
|
||||||
|
path = Path.GetFullPath(path);
|
||||||
|
basePath = Path.GetFullPath(basePath);
|
||||||
|
if (String.Equals(path, basePath, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return "."; // the "this folder"
|
||||||
|
|
||||||
|
if (path.StartsWith(basePath + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return path.Substring(basePath.Length + 1);
|
||||||
|
|
||||||
|
//handle different drives
|
||||||
|
string pathRoot = Path.GetPathRoot(path);
|
||||||
|
if (!String.Equals(pathRoot, Path.GetPathRoot(basePath), StringComparison.OrdinalIgnoreCase))
|
||||||
|
return path;
|
||||||
|
|
||||||
|
//handle ".." pathes
|
||||||
|
string[] pathParts = path.Substring(pathRoot.Length).Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||||
|
string[] basePathParts = basePath.Substring(pathRoot.Length).Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||||
|
|
||||||
|
int commonFolderCount = 0;
|
||||||
|
while (commonFolderCount < pathParts.Length && commonFolderCount < basePathParts.Length &&
|
||||||
|
String.Equals(pathParts[commonFolderCount], basePathParts[commonFolderCount], StringComparison.OrdinalIgnoreCase))
|
||||||
|
commonFolderCount++;
|
||||||
|
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (int i = 0; i < basePathParts.Length - commonFolderCount; i++)
|
||||||
|
{
|
||||||
|
result.Append("..");
|
||||||
|
result.Append(Path.DirectorySeparatorChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathParts.Length - commonFolderCount == 0)
|
||||||
|
return result.ToString().TrimEnd(Path.DirectorySeparatorChar);
|
||||||
|
|
||||||
|
result.Append(String.Join(Path.DirectorySeparatorChar.ToString(), pathParts, commonFolderCount, pathParts.Length - commonFolderCount));
|
||||||
|
return result.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method accepts two strings the represent two files to
|
||||||
|
// compare. A return value of true indicates that the contents of the files
|
||||||
|
// are the same. A return value of any other value indicates that the
|
||||||
|
// files are not the same.
|
||||||
|
public static bool FileCompare(string filePath1, string filePath2)
|
||||||
|
{
|
||||||
|
int file1byte;
|
||||||
|
int file2byte;
|
||||||
|
|
||||||
|
// Determine if the same file was referenced two times.
|
||||||
|
if (String.Equals(filePath1, filePath2, StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
// Return true to indicate that the files are the same.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the two files.
|
||||||
|
using (FileStream fs1 = new FileStream(filePath1, FileMode.Open, FileAccess.Read))
|
||||||
|
using (FileStream fs2 = new FileStream(filePath2, FileMode.Open, FileAccess.Read))
|
||||||
|
{
|
||||||
|
// Check the file sizes. If they are not the same, the files
|
||||||
|
// are not the same.
|
||||||
|
if (fs1.Length != fs2.Length)
|
||||||
|
{
|
||||||
|
// Return false to indicate files are different
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read and compare a byte from each file until either a
|
||||||
|
// non-matching set of bytes is found or until the end of
|
||||||
|
// file1 is reached.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Read one byte from each file.
|
||||||
|
file1byte = fs1.ReadByte();
|
||||||
|
file2byte = fs2.ReadByte();
|
||||||
|
} while ((file1byte == file2byte) && (file1byte != -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the success of the comparison. "file1byte" is
|
||||||
|
// equal to "file2byte" at this point only if the files are
|
||||||
|
// the same.
|
||||||
|
return ((file1byte - file2byte) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CopyDirectory(string sourcePath, string destPath, bool cleanDestination = true)
|
||||||
|
{
|
||||||
|
if (cleanDestination)
|
||||||
|
EnsureEmptyFolder(destPath);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(destPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(destPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string file in Directory.GetFiles(sourcePath))
|
||||||
|
{
|
||||||
|
var fileName = Path.GetFileName(file);
|
||||||
|
Debug.Assert(fileName != null);
|
||||||
|
string dest = Path.Combine(destPath, fileName);
|
||||||
|
File.Copy(file, dest, true);
|
||||||
|
File.SetAttributes(dest, File.GetAttributes(dest) & (~FileAttributes.ReadOnly));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string folder in Directory.GetDirectories(sourcePath))
|
||||||
|
{
|
||||||
|
var folderName = Path.GetFileName(folder);
|
||||||
|
Debug.Assert(folderName != null);
|
||||||
|
string dest = Path.Combine(destPath, folderName);
|
||||||
|
CopyDirectory(folder, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnsureEmptyFolder(string folderName)
|
||||||
|
{
|
||||||
|
folderName = Path.GetFullPath(folderName);
|
||||||
|
|
||||||
|
if (!Directory.Exists(folderName))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(folderName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteFolderContent(folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnsureFolderOfFile(string filePath)
|
||||||
|
{
|
||||||
|
string directory = Path.GetDirectoryName(filePath);
|
||||||
|
if (directory != null && !Directory.Exists(directory))
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void Retry(int number, Action action)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException)
|
||||||
|
{
|
||||||
|
var i = number - 1;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
throw;
|
||||||
|
|
||||||
|
Retry(i, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DeleteFolderContent(string folderName)
|
||||||
|
{
|
||||||
|
foreach (string file in Directory.GetFiles(folderName))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Retry(5, () => File.Delete(file));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception("Unable to delete file: " + file, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string folder in Directory.GetDirectories(folderName))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Retry(5, () => Directory.Delete(folder, true));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception("Unable to delete folder: " + folder, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DeleteFolder(string path)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
DeleteFolderContent(path);
|
||||||
|
|
||||||
|
Retry(5, () => Directory.Delete(path, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Resources;
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public class GenerateCapnpFileCodeBehindTask : Task
|
||||||
|
{
|
||||||
|
public GenerateCapnpFileCodeBehindTask()
|
||||||
|
{
|
||||||
|
CodeBehindGenerator = new FeatureFileCodeBehindGenerator(Log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICapnpCsharpGenerator CodeBehindGenerator { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string ProjectPath { get; set; }
|
||||||
|
|
||||||
|
public string RootNamespace { get; set; }
|
||||||
|
|
||||||
|
public string ProjectFolder => Path.GetDirectoryName(ProjectPath);
|
||||||
|
public string OutputPath { get; set; }
|
||||||
|
|
||||||
|
public ITaskItem[] CapnpFiles { get; set; }
|
||||||
|
|
||||||
|
public ITaskItem[] GeneratorPlugins { get; set; }
|
||||||
|
|
||||||
|
[Output]
|
||||||
|
public ITaskItem[] GeneratedFiles { get; private set; }
|
||||||
|
|
||||||
|
public override bool Execute()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var currentProcess = Process.GetCurrentProcess();
|
||||||
|
|
||||||
|
Log.LogWithNameTag(Log.LogMessage, $"process: {currentProcess.ProcessName}, pid: {currentProcess.Id}, CD: {Environment.CurrentDirectory}");
|
||||||
|
|
||||||
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
Log.LogWithNameTag(Log.LogMessage, " " + assembly.FullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.LogWithNameTag(Log.LogMessage, $"Error when dumping process info: {e}");
|
||||||
|
}
|
||||||
|
|
||||||
|
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||||
|
|
||||||
|
var generator = CodeBehindGenerator ?? new FeatureFileCodeBehindGenerator(Log);
|
||||||
|
|
||||||
|
Log.LogWithNameTag(Log.LogMessage, "Starting GenerateFeatureFileCodeBehind");
|
||||||
|
|
||||||
|
var generatorPlugins = GeneratorPlugins?.Select(gp => gp.ItemSpec).ToList() ?? new List<string>();
|
||||||
|
|
||||||
|
var capnpFiles = CapnpFiles?.Select(i => i.ItemSpec).ToList() ?? new List<string>();
|
||||||
|
|
||||||
|
var generatedFiles = generator.GenerateFilesForProject(
|
||||||
|
ProjectPath,
|
||||||
|
RootNamespace,
|
||||||
|
capnpFiles,
|
||||||
|
generatorPlugins,
|
||||||
|
ProjectFolder,
|
||||||
|
OutputPath);
|
||||||
|
|
||||||
|
GeneratedFiles = generatedFiles.Select(file => new TaskItem { ItemSpec = file }).ToArray();
|
||||||
|
|
||||||
|
return !Log.HasLoggedErrors;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (e.InnerException != null)
|
||||||
|
{
|
||||||
|
if (e.InnerException is FileLoadException fle)
|
||||||
|
{
|
||||||
|
Log?.LogWithNameTag(Log.LogError, $"FileLoadException Filename: {fle.FileName}");
|
||||||
|
Log?.LogWithNameTag(Log.LogError, $"FileLoadException FusionLog: {fle.FusionLog}");
|
||||||
|
Log?.LogWithNameTag(Log.LogError, $"FileLoadException Message: {fle.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Log?.LogWithNameTag(Log.LogError, e.InnerException.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Log?.LogWithNameTag(Log.LogError, e.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||||
|
{
|
||||||
|
Log.LogWithNameTag(Log.LogMessage, args.Name);
|
||||||
|
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
22
Capnpc.Csharp.MsBuild.Generation/Helper/LogExtensions.cs
Normal file
22
Capnpc.Csharp.MsBuild.Generation/Helper/LogExtensions.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public static class LogExtensions
|
||||||
|
{
|
||||||
|
public static void LogWithNameTag(
|
||||||
|
this TaskLoggingHelper loggingHelper,
|
||||||
|
Action<string, object[]> loggingMethod,
|
||||||
|
string message,
|
||||||
|
params object[] messageArgs)
|
||||||
|
{
|
||||||
|
string fullMessage = $"[SpecFlow] {message}";
|
||||||
|
loggingMethod?.Invoke(fullMessage, messageArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public interface ICapnpCsharpGenerator
|
||||||
|
{
|
||||||
|
IEnumerable<string> GenerateFilesForProject(string projectPath, string rootNamespace, List<string> CapnpFiles, List<string> generatorPlugins, string projectFolder, string outputPath);
|
||||||
|
}
|
||||||
|
}
|
42
Capnpc.Csharp.MsBuild.Generation/TestFileGeneratorResult.cs
Normal file
42
Capnpc.Csharp.MsBuild.Generation/TestFileGeneratorResult.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public class TestFileGeneratorResult
|
||||||
|
{
|
||||||
|
public TestFileGeneratorResult(TestGeneratorResult generatorResult, string fileName)
|
||||||
|
{
|
||||||
|
if (generatorResult == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(generatorResult));
|
||||||
|
}
|
||||||
|
|
||||||
|
Filename = fileName ?? throw new ArgumentNullException(nameof(fileName));
|
||||||
|
|
||||||
|
Errors = generatorResult.Errors;
|
||||||
|
IsUpToDate = generatorResult.IsUpToDate;
|
||||||
|
GeneratedTestCode = generatorResult.GeneratedTestCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The errors, if any.
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<TestGenerationError> Errors { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The generated file was up-to-date.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsUpToDate { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The generated test code.
|
||||||
|
/// </summary>
|
||||||
|
public string GeneratedTestCode { get; }
|
||||||
|
|
||||||
|
public bool Success => Errors == null || !Errors.Any();
|
||||||
|
|
||||||
|
public string Filename { get; }
|
||||||
|
}
|
||||||
|
}
|
6
Capnpc.Csharp.MsBuild.Generation/TestGenerationError.cs
Normal file
6
Capnpc.Csharp.MsBuild.Generation/TestGenerationError.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public class TestGenerationError
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
11
Capnpc.Csharp.MsBuild.Generation/TestGeneratorResult.cs
Normal file
11
Capnpc.Csharp.MsBuild.Generation/TestGeneratorResult.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Capnpc.Csharp.MsBuild.Generation
|
||||||
|
{
|
||||||
|
public class TestGeneratorResult
|
||||||
|
{
|
||||||
|
public IEnumerable<TestGenerationError> Errors { get; internal set; }
|
||||||
|
public bool IsUpToDate { get; internal set; }
|
||||||
|
public string GeneratedTestCode { get; internal set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<CpsExtensionSchemaDirectory Condition="'$(CpsExtensionSchemaDirectory)' == ''">$(MSBuildThisFileDirectory)Rules\</CpsExtensionSchemaDirectory>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PropertyPageSchema Include="$(CpsExtensionSchemaDirectory)\ProjectItemsSchema.xaml;"/>
|
||||||
|
|
||||||
|
<PropertyPageSchema Include="$(CpsExtensionSchemaDirectory)\FeatureFileType.xaml;">
|
||||||
|
<Context>File;BrowseObject</Context>
|
||||||
|
</PropertyPageSchema>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Copyright, Microsoft Corporation, All rights reserved.-->
|
||||||
|
|
||||||
|
<Rule
|
||||||
|
Name="Feature"
|
||||||
|
DisplayName="Feature"
|
||||||
|
PageTemplate="tool"
|
||||||
|
Description="SpecFlow Feature file"
|
||||||
|
xmlns="http://schemas.microsoft.com/build/2009/properties">
|
||||||
|
|
||||||
|
<Rule.DataSource>
|
||||||
|
<DataSource Persistence="ProjectFile" HasConfigurationCondition="True" ItemType="CapnpFiles" />
|
||||||
|
</Rule.DataSource>
|
||||||
|
|
||||||
|
|
||||||
|
<StringProperty Name="Identity" DisplayName="File Name" ReadOnly="true" Category="Misc">
|
||||||
|
<StringProperty.DataSource>
|
||||||
|
<DataSource Persistence="Intrinsic" ItemType="CapnpFiles" PersistedName="Identity" />
|
||||||
|
</StringProperty.DataSource>
|
||||||
|
</StringProperty>
|
||||||
|
|
||||||
|
<StringProperty Name="FullPath" DisplayName="Full Path" ReadOnly="true" Category="Misc">
|
||||||
|
<StringProperty.DataSource>
|
||||||
|
<DataSource Persistence="Intrinsic" ItemType="CapnpFiles" PersistedName="FullPath" />
|
||||||
|
</StringProperty.DataSource>
|
||||||
|
</StringProperty>
|
||||||
|
|
||||||
|
<!--<BoolProperty Name="Visible" Visible="true" />-->
|
||||||
|
<StringProperty Name="DependentUpon" Visible="false" />
|
||||||
|
<StringProperty Name="Link" Visible="false" />
|
||||||
|
<StringProperty Name="Generator" Visible="true" DisplayName="Custom Tool"/>
|
||||||
|
|
||||||
|
|
||||||
|
</Rule>
|
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Copyright, Microsoft Corporation, All rights reserved.-->
|
||||||
|
<ProjectSchemaDefinitions
|
||||||
|
xmlns="http://schemas.microsoft.com/build/2009/properties">
|
||||||
|
|
||||||
|
<ContentType
|
||||||
|
Name="FeatureFile"
|
||||||
|
DisplayName="FeatureFileType source file"
|
||||||
|
ItemType="CapnpFiles">
|
||||||
|
<NameValuePair Name="DependentExtensions" Value=".feature.cs" />
|
||||||
|
|
||||||
|
</ContentType>
|
||||||
|
|
||||||
|
<ItemType Name="CapnpFiles" DisplayName="Feature file"/>
|
||||||
|
|
||||||
|
<FileExtension Name=".feature" ContentType="FeatureFile" />
|
||||||
|
|
||||||
|
</ProjectSchemaDefinitions>
|
@ -0,0 +1,77 @@
|
|||||||
|
<Project TreatAsLocalProperty="TaskFolder;TaskAssembly">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<CapnpcCsharp_CpsExtensionDesignTimeTargetsPath Condition="'$(CapnpcCsharp_CpsExtensionDesignTimeTargetsPath)' == ''">$(MSBuildThisFileDirectory)CPS\Buildsystem\CpsExtension.DesignTime.targets</CapnpcCsharp_CpsExtensionDesignTimeTargetsPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Import Project="$(CapnpcCsharp_CpsExtensionDesignTimeTargetsPath)" Condition="'$(DesignTimeBuild)' == 'true' " />
|
||||||
|
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<CapnpcCsharp_UseHostCompilerIfAvailable Condition="'$(CapnpcCsharp_UseHostCompilerIfAvailable)'==''">false</CapnpcCsharp_UseHostCompilerIfAvailable>
|
||||||
|
<UseHostCompilerIfAvailable>$(CapnpcCsharp_UseHostCompilerIfAvailable)</UseHostCompilerIfAvailable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OverwriteReadOnlyFiles Condition="'$(OverwriteReadOnlyFiles)'==''">false</OverwriteReadOnlyFiles>
|
||||||
|
<ForceGeneration Condition="'$(ForceGeneration)'==''">false</ForceGeneration>
|
||||||
|
|
||||||
|
<ShowTrace Condition="'$(ShowTrace)'==''">false</ShowTrace>
|
||||||
|
<VerboseOutput Condition="'$(VerboseOutput)'==''">true</VerboseOutput>
|
||||||
|
<CapnpcCsharp_DebugMSBuildTask Condition="'$(CapnpcCsharp_DebugMSBuildTask)' == ''">false</CapnpcCsharp_DebugMSBuildTask>
|
||||||
|
|
||||||
|
<_SpecFlowPropsImported Condition="'$(_SpecFlowPropsImported)'==''">true</_SpecFlowPropsImported>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
property group for feature flags
|
||||||
|
-->
|
||||||
|
<PropertyGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
feature flag to enable experimental support for cleaning up generated code-behind files during rebuild and clean scenarios
|
||||||
|
-->
|
||||||
|
<CapnpcCsharp_DeleteCodeBehindFilesOnCleanRebuild Condition="'$(CapnpcCsharp_DeleteCodeBehindFilesOnCleanRebuild)'==''">false</CapnpcCsharp_DeleteCodeBehindFilesOnCleanRebuild>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
net.sdk support: feature flag to enable experimental support for net.sdk project system
|
||||||
|
-->
|
||||||
|
<CapnpcCsharp_EnableDefaultCompileItems Condition="'$(CapnpcCsharp_EnableDefaultCompileItems)'==''">true</CapnpcCsharp_EnableDefaultCompileItems>
|
||||||
|
<CapnpcCsharp_EnableWarnForFeatureCodeBehindFilesWithoutCorrespondingFeatureFile Condition="'$(CapnpcCsharp_EnableWarnForFeatureCodeBehindFilesWithoutCorrespondingFeatureFile)'==''">$(CapnpcCsharp_EnableDefaultCompileItems)</CapnpcCsharp_EnableWarnForFeatureCodeBehindFilesWithoutCorrespondingFeatureFile>
|
||||||
|
|
||||||
|
<DefaultItemExcludes>$(DefaultItemExcludes);**/*.feature</DefaultItemExcludes>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<CapnpFiles Include="**\*.capnp" >
|
||||||
|
<CodeBehindFile>%(RelativeDir)%(Filename).capnp(DefaultLanguageSourceExtension)</CodeBehindFile>
|
||||||
|
<Visible>$(UsingMicrosoftNETSdk)</Visible>
|
||||||
|
</CapnpFiles>
|
||||||
|
|
||||||
|
<!-- obsolete codebehind files, scenarios:
|
||||||
|
- after rename operation
|
||||||
|
- after deletion of a feature file
|
||||||
|
- after pulling latest changes from version control with above changes
|
||||||
|
-->
|
||||||
|
<SpecFlowObsoleteCodeBehindFiles Include="**\*.capnp(DefaultLanguageSourceExtension)" Exclude="@(CapnpFiles->'%(CodeBehindFile)')" />
|
||||||
|
|
||||||
|
<!-- Support for Visual Studio Incremental Build
|
||||||
|
https://github.com/techtalk/SpecFlow/issues/1319
|
||||||
|
-->
|
||||||
|
<UpToDateCheckInput Include="@(CapnpFiles)" />
|
||||||
|
<UpToDateCheckBuild Include="@(CapnpFiles->'%(CodeBehindFile)')" Original="@(CapnpFiles)" />
|
||||||
|
<CustomAdditionalCompileInputs Include="@(CapnpFiles->'%(CodeBehindFile)')" />
|
||||||
|
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<_CapnpcCsharp_TaskFolder Condition=" '$(MSBuildRuntimeType)' == 'Core' And '$(_CapnpcCsharp_TaskFolder)' == ''">netcoreapp2.0</_CapnpcCsharp_TaskFolder>
|
||||||
|
<_CapnpcCsharp_TaskFolder Condition=" '$(MSBuildRuntimeType)' != 'Core' And '$(_CapnpcCsharp_TaskFolder)' == ''">net471</_CapnpcCsharp_TaskFolder>
|
||||||
|
<_CapnpcCsharp_TaskAssembly Condition=" '$(_CapnpcCsharp_TaskAssembly)' == '' ">..\tasks\$(_CapnpcCsharp_TaskFolder)\Capnpc.Csharp.MsBuild.Generation.dll</_CapnpcCsharp_TaskAssembly>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Import Project="Capnpc.Csharp.MsBuild.Generation.tasks"/>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,145 @@
|
|||||||
|
<Project>
|
||||||
|
|
||||||
|
<Import Project="Capnpc.Csharp.MsBuild.Generation.props" Condition="'$(_SpecFlowPropsImported)'==''"/>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(BuildServerMode)' == ''">
|
||||||
|
<BuildServerMode Condition="'$(BuildingInsideVisualStudio)'=='true'">false</BuildServerMode>
|
||||||
|
<BuildServerMode Condition="'$(BuildingInsideVisualStudio)'!='true'">true</BuildServerMode>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
net.sdk experimental support:
|
||||||
|
- currently we only want to support either classic project system or netsdk project system.
|
||||||
|
- currently we don't want to support globbing with classic project system => ensure globbing only get enabled with 'UsingMicrosoftNETSdk'
|
||||||
|
- currently we are supporting $(EnableDefaultCompileItems) for disabling globbing support for codebehind files
|
||||||
|
-->
|
||||||
|
<_CapnpcCsharp_EnableDefaultCompileItems Condition="'$(CapnpcCsharp_EnableDefaultCompileItems)' == '' And '$(UsingMicrosoftNETSdk)' == 'true'">true</_CapnpcCsharp_EnableDefaultCompileItems>
|
||||||
|
<_CapnpcCsharp_EnableDefaultCompileItems Condition="'$(CapnpcCsharp_EnableDefaultCompileItems)' == 'true' And '$(UsingMicrosoftNETSdk)' == 'true'">true</_CapnpcCsharp_EnableDefaultCompileItems>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<BuildDependsOn>
|
||||||
|
BeforeUpdateCapnpFilesInProject;
|
||||||
|
UpdateCapnpFilesInProject;
|
||||||
|
IncludeCodeBehindFilesInProject;
|
||||||
|
AfterUpdateCapnpFilesInProject;
|
||||||
|
$(BuildDependsOn)
|
||||||
|
</BuildDependsOn>
|
||||||
|
<CleanDependsOn>
|
||||||
|
CleanCapnpFilesInProject;
|
||||||
|
$(CleanDependsOn)
|
||||||
|
</CleanDependsOn>
|
||||||
|
<RebuildDependsOn>
|
||||||
|
SwitchToForceGenerate;
|
||||||
|
$(RebuildDependsOn)
|
||||||
|
</RebuildDependsOn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
net.sdk support: update default compile items to show generated files as nested items
|
||||||
|
-->
|
||||||
|
<ItemGroup Condition="'$(_CapnpcCsharp_EnableDefaultCompileItems)' == 'true' and '$(EnableDefaultItems)' == 'true' ">
|
||||||
|
<Compile Update="@(CapnpFiles->'%(CodeBehindFile)')"
|
||||||
|
DependentUpon="%(Filename)"
|
||||||
|
AutoGen="true"
|
||||||
|
DesignTime="true"
|
||||||
|
Visible="true"
|
||||||
|
Condition="'$(EnableDefaultCompileItems)' == 'true'" />
|
||||||
|
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<Target Name="WarnForFeatureCodeBehindFilesWithoutCorrespondingFeatureFile" AfterTargets="CoreCompile"
|
||||||
|
Condition="'$(CapnpcCsharp_EnableWarnForFeatureCodeBehindFilesWithoutCorrespondingFeatureFile)' == 'true'">
|
||||||
|
<Warning Text="For codebehind file '@(SpecFlowObsoleteCodeBehindFiles)', no feature file was found." File="@(SpecFlowObsoleteCodeBehindFiles)" Condition="'@(SpecFlowObsoleteCodeBehindFiles)' != ''" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
|
||||||
|
<Target Name="SwitchToForceGenerate">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ForceGeneration>true</ForceGeneration>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
|
||||||
|
<Target Name="UpdateCapnpFilesInProject"
|
||||||
|
DependsOnTargets="BeforeUpdateCapnpFilesInProject">
|
||||||
|
|
||||||
|
<Message Text="CapnpFiles: @(CapnpFiles)" Importance="high" Condition="'$(VerboseOutput)' == 'true'" />
|
||||||
|
|
||||||
|
<Error
|
||||||
|
Text="CapnpCsharp codebehind generation is not compatible with MSBuild codebehind generation. The custom tool must be removed from the file."
|
||||||
|
File="@(None)"
|
||||||
|
Condition="%(None.Extension) == '.feature' AND %(None.Generator) == 'SpecFlowSingleFileGenerator'"/>
|
||||||
|
|
||||||
|
<!-- <PropertyGroup>
|
||||||
|
<SpecFlowCodeBehindOutputPath Condition="'$(SpecFlowCodeBehindOutputPath)' == ''">Features.Generated</SpecFlowCodeBehindOutputPath>
|
||||||
|
</PropertyGroup> -->
|
||||||
|
|
||||||
|
<GenerateFeatureFileCodeBehindTask
|
||||||
|
ProjectPath="$(MSBuildProjectFullPath)"
|
||||||
|
OutputPath="$(SpecFlowCodeBehindOutputPath)"
|
||||||
|
CapnpFiles="@(CapnpFiles)"
|
||||||
|
RootNamespace="$(RootNamespace)"
|
||||||
|
GeneratorPlugins="@(SpecFlowGeneratorPlugins)" >
|
||||||
|
|
||||||
|
<Output TaskParameter="GeneratedFiles" ItemName="CapnpCsharpGeneratedFiles" />
|
||||||
|
</GenerateFeatureFileCodeBehindTask>
|
||||||
|
|
||||||
|
<Message Text="CapnpCsharpGeneratedFiles: %(CapnpCsharpGeneratedFiles.Identity)" Importance="high" Condition="'$(VerboseOutput)' == 'true'" />
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
net.sdk support: globbing does not support including files which are dynamically generated inside targets, we have to manually update compile items
|
||||||
|
-->
|
||||||
|
<ItemGroup Condition="'$(_CapnpcCsharp_EnableDefaultCompileItems)' == 'true' and '$(EnableDefaultItems)' == 'true' and '$(EnableDefaultCompileItems)' == 'true'">
|
||||||
|
|
||||||
|
<!-- if this is the first time generation of codebehind files, we have to manually add them as compile items -->
|
||||||
|
<Compile Include="@(CapnpFiles->'%(CodeBehindFile)')"
|
||||||
|
Exclude="@(Compile)"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
eather if codebehind files are added manually to compile item group or are added by net.sdk globbing support,
|
||||||
|
ensure they are nested under feature files like in previous specflow versions
|
||||||
|
currently, we cannot use itemgroup update attribute inside a target because of some bugs in MSBuild (all items will be updated)
|
||||||
|
- https://github.com/Microsoft/msbuild/issues/1618
|
||||||
|
- https://github.com/Microsoft/msbuild/issues/2835
|
||||||
|
- https://github.com/Microsoft/msbuild/issues/1124
|
||||||
|
-->
|
||||||
|
<Compile DependentUpon="@(CapnpFiles)"
|
||||||
|
AutoGen="true"
|
||||||
|
DesignTime="true"
|
||||||
|
Visible="true"
|
||||||
|
Condition="'%(Compile.Identity)' == '@(CapnpFiles->'%(CodeBehindFile)')'" />
|
||||||
|
|
||||||
|
<!-- remove files which got obsolete, typically after rename operation, or getting changes from source control -->
|
||||||
|
<Compile Remove="@(SpecFlowObsoleteCodeBehindFiles)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="BeforeUpdateCapnpFilesInProject">
|
||||||
|
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="IncludeCodeBehindFilesInProject" DependsOnTargets="UpdateCapnpFilesInProject">
|
||||||
|
<ItemGroup Condition="'$(UsingMicrosoftNETSdk)' != 'true'">
|
||||||
|
<Compile Include="@(CapnpCsharpGeneratedFiles)" Exclude="@(Compile)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="AfterUpdateCapnpFilesInProject" DependsOnTargets="IncludeCodeBehindFilesInProject">
|
||||||
|
<!-- include any generated SpecFlow files in the compilation of the project if not included yet -->
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CleanCapnpFilesInProject" Condition="'$(CapnpcCsharp_DeleteCodeBehindFilesOnCleanRebuild)' == 'true'">
|
||||||
|
<!-- remove known codebehind files for existing feature files -->
|
||||||
|
<Delete Files="%(CapnpFiles.CodeBehindFile)" ContinueOnError="true" />
|
||||||
|
|
||||||
|
<!-- remove obsolete codebehind files, scenarios:
|
||||||
|
- after rename operation
|
||||||
|
- after deletion of a feature file
|
||||||
|
- after pulling latest changes from version control with above changes
|
||||||
|
-->
|
||||||
|
<Delete Files="@(SpecFlowObsoleteCodeBehindFiles)" ContinueOnError="true" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
@ -0,0 +1,3 @@
|
|||||||
|
<Project>
|
||||||
|
<UsingTask TaskName="Capnpc.Csharp.MsBuild.Generation.GenerateFeatureFileCodeBehindTask" AssemblyFile="$(_CapnpcCsharp_TaskAssembly)" />
|
||||||
|
</Project>
|
@ -0,0 +1,5 @@
|
|||||||
|
<Project TreatAsLocalProperty="TaskFolder;TaskAssembly">
|
||||||
|
|
||||||
|
<Import Project="..\build\Capnpc.Csharp.MsBuild.Generation.props"/>
|
||||||
|
|
||||||
|
</Project>
|
31
Licenses/SpecFlow-LICENSE-NewBSD.txt
Normal file
31
Licenses/SpecFlow-LICENSE-NewBSD.txt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
SpecFlow Licence (New BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2009, TechTalk
|
||||||
|
|
||||||
|
Disclaimer:
|
||||||
|
* The initial codebase of Specflow was written by TechTalk employees.
|
||||||
|
No 3rd party code was included.
|
||||||
|
* No code of customer projects was used to create this project.
|
||||||
|
* TechTalk had the full rights to publish the initial codebase.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the SpecFlow project nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL TECHTALK OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
Loading…
x
Reference in New Issue
Block a user