diff --git a/Mono.TextTemplating.Build/Mono.TextTemplating.Build.csproj b/Mono.TextTemplating.Build/Mono.TextTemplating.Build.csproj index df1e20f..c75dc30 100644 --- a/Mono.TextTemplating.Build/Mono.TextTemplating.Build.csproj +++ b/Mono.TextTemplating.Build/Mono.TextTemplating.Build.csproj @@ -1,4 +1,4 @@ - + net48;net6.0 @@ -14,15 +14,15 @@ readme.md - - - <_PackageFiles Include="T4.BuildTools.props" PackagePath="build\$(PackageId).props" Pack="true" /> - <_PackageFiles Include="T4.BuildTools.targets" PackagePath="build\$(PackageId).targets" Pack="true" /> - <_PackageFiles Include="multitargeting.props" PackagePath="buildMultiTargeting\$(PackageId).props" Pack="true" /> - <_PackageFiles Include="multitargeting.targets" PackagePath="buildMultiTargeting\$(PackageId).targets" Pack="true" /> - <_PackageFiles Include="T4.BuildTools.targets.buildschema.json" PackagePath="build\$(PackageId).targets.buildschema.json" Pack="true" /> - - + + + + + + + + + diff --git a/Mono.TextTemplating.Build/T4.BuildTools.props b/Mono.TextTemplating.Build/T4.BuildTools.props index b67947a..40c97a1 100644 --- a/Mono.TextTemplating.Build/T4.BuildTools.props +++ b/Mono.TextTemplating.Build/T4.BuildTools.props @@ -1,11 +1,6 @@ - - false - true - - + - False @@ -24,18 +19,30 @@ False - + + + + - MSBuild:TransformAll + MSBuild:TransformTemplates - MSBuild:TransformAll + MSBuild:TransformTemplates - + - + + Project + + + File;BrowseObject + + \ No newline at end of file diff --git a/Mono.TextTemplating.Build/T4.BuildTools.targets.buildschema.json b/Mono.TextTemplating.Build/T4.BuildTools.targets.buildschema.json index eee551f..cc8b4ad 100644 --- a/Mono.TextTemplating.Build/T4.BuildTools.targets.buildschema.json +++ b/Mono.TextTemplating.Build/T4.BuildTools.targets.buildschema.json @@ -18,7 +18,7 @@ } }, "T4Argument": { - "description": "T4 template argument, optionally scoped to a directive and/or directive processor. The value, processor and directive may be provided using the `Value, `Processor` and `Directive metadata, or encoded into the `Include` with the syntax `name=value`, `directive!name!value` or `processor!directive!name!value`.", + "description": "T4 template argument, optionally scoped to a directive and/or directive processor. The value, processor and directive may be provided using the `Value, `Processor` and `Directive metadata, or encoded into the `Include` with the format `name=value`, `directive!name!value` or `processor!directive!name!value`.", "includeDescription": "T4 argument name", "metadata": { "Value": "The T4 argument value. Overrides any value encoded in the `Include`.", @@ -55,15 +55,15 @@ "type": "file" }, "T4RequiredAssemblies": { - "description": "After running the TransformTemplates target, the assemblies that must be referenced to compile the preprocessed templates", + "description": "After running the `TransformTemplates` target, the assemblies that must be referenced to compile the preprocessed templates", "type": "file" }, "GeneratedTemplates": { - "description": "After running the TransformTemplates target, the output of all transformed templates", + "description": "After running the `TransformTemplates` target, the output of all transformed templates", "type": "file" }, "PreprocessedTemplates": { - "description": "After running the TransformTemplates target, the output of all preprocessed templates", + "description": "After running the `TransformTemplates` target, the output of all preprocessed templates", "type": "file" } }, @@ -79,6 +79,18 @@ "description": "Overrides the output filename for a T4 template. Note that Visual Studio does not respect this.", "type": "file" } + }, + { + "$appliesTo": [ "GeneratedTemplates", "PreprocessedTemplates" ], + "InputFile": { + "description": "The original template file that generated this file", + "type": "file" + }, + "Dependencies": { + "description": "The files that the template depends on", + "type": "file", + "isList": true + } } ], "properties": { @@ -93,20 +105,20 @@ "defaultValue": "true" }, "TransformFile": { - "description": "The T4 files to transform when running the Transform target", + "description": "The T4 files to transform when running the `Transform` target", "type": "file", "isList": true }, "BeforeTransform": { "description": "Targets to run before the T4 Transform target", "type": "target-name", - "deprecationMessage": "Use `BeforeTargets=\"TransformTemplatesCore\" for target ordering`", + "deprecationMessage": "Use `BeforeTargets=\"TransformTemplatesCore\"` for target ordering.", "isList": true }, "AfterTransform": { "description": "Targets to run after the T4 Transform target", "type": "target-name", - "deprecationMessage": "Use `AfterTargets=\"TransformTemplatesCore\" for target ordering`", + "deprecationMessage": "Use `AfterTargets=\"TransformTemplatesCore\"` for target ordering.", "isList": true }, "IncludeFolders": { @@ -122,20 +134,15 @@ "PreprocessTemplateDefaultNamespace": { "description": "Default namespace for preprocessed templates", "defaultValue": "$(RootNamespace)", - "deprecationMessage": "Legacy alternative to`$(T4DefaultNamespace)`" + "deprecationMessage": "Legacy alternative to `$(T4DefaultNamespace)`" }, "UseLegacyT4Preprocessing": { "description": "Place preprocessed templates beside the templates instead of dynamically injecting them into the build.", "type": "bool" }, "T4Arguments": { - "description": "Semicolon-separated list of values to convert to `@(T4Argument)` items. Intended to be used from command-line invocations only.", - "isList": true, - "type": { - "description": "Key-value pair", - "allowUnknownValues": true, - "values": {} - } + "description": "Used to pass arguments when invoking on the CLI. This is a semicolon-separated list and uses the same format as encoded `T4Argument` items: `name=value`, `directive!name!value` or `processor!directive!name!value`.", + "isList": true } }, "targets": { diff --git a/Mono.TextTemplating.Build/T4PropertyPage.xaml b/Mono.TextTemplating.Build/T4PropertyPage.xaml new file mode 100644 index 0000000..96f7258 --- /dev/null +++ b/Mono.TextTemplating.Build/T4PropertyPage.xaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Mono.TextTemplating.Build/T4PropertySchema.xaml b/Mono.TextTemplating.Build/T4PropertySchema.xaml new file mode 100644 index 0000000..38d9b76 --- /dev/null +++ b/Mono.TextTemplating.Build/T4PropertySchema.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + diff --git a/Mono.TextTemplating.Build/TextTransform.cs b/Mono.TextTemplating.Build/TextTransform.cs index 32558e4..79a4e02 100644 --- a/Mono.TextTemplating.Build/TextTransform.cs +++ b/Mono.TextTemplating.Build/TextTransform.cs @@ -135,14 +135,16 @@ public override bool Execute () if (buildState.TransformTemplates != null) { TransformTemplateOutput = new ITaskItem[buildState.TransformTemplates.Count]; for (int i = 0; i < buildState.TransformTemplates.Count; i++) { - TransformTemplateOutput[i] = new TaskItem (buildState.TransformTemplates[i].OutputFile); + var template = buildState.TransformTemplates[i]; + TransformTemplateOutput[i] = ConstructOutputItem (template.OutputFile, template.InputFile, template.Dependencies); } } if (buildState.PreprocessTemplates != null) { PreprocessedTemplateOutput = new ITaskItem[buildState.PreprocessTemplates.Count]; for (int i = 0; i < buildState.PreprocessTemplates.Count; i++) { - PreprocessedTemplateOutput[i] = new TaskItem (buildState.PreprocessTemplates[i].OutputFile); + var template = buildState.PreprocessTemplates[i]; + PreprocessedTemplateOutput[i] = ConstructOutputItem (template.OutputFile, template.InputFile, template.Dependencies); } } @@ -159,6 +161,18 @@ public override bool Execute () return success; } + static TaskItem ConstructOutputItem (string outputFile, string inputFile, List itemDependencies) + { + var item = new TaskItem (outputFile); + item.SetMetadata ("InputFile", inputFile); + + if (itemDependencies?.Count > 0) { + item.SetMetadata ("Dependencies", string.Join (";", itemDependencies)); + } + + return item; + } + bool AddParameters (TemplateBuildState buildState) { bool success = true; diff --git a/Mono.TextTemplating.Build/TextTransformProcessor.cs b/Mono.TextTemplating.Build/TextTransformProcessor.cs index e0eb29b..3854cd2 100644 --- a/Mono.TextTemplating.Build/TextTransformProcessor.cs +++ b/Mono.TextTemplating.Build/TextTransformProcessor.cs @@ -80,6 +80,9 @@ public static bool Process (TaskLoggingHelper taskLog, TemplateBuildState previo var pt = LoadTemplate (generator, inputFile, out var inputContent); TemplateSettings settings = TemplatingEngine.GetSettings (generator, pt); + settings.RelativeLinePragmas = true; + settings.RelativeLinePragmasBaseDirectory = Path.GetDirectoryName (preprocess.OutputFile); + settings.CodeGenerationOptions.UseRemotingCallContext = buildState.PreprocessTargetRuntimeIdentifier == ".NETFramework"; // FIXME: make these configurable, take relative path into account @@ -208,8 +211,6 @@ static MSBuildTemplateGenerator CreateGenerator (TemplateBuildState buildState) } } - generator.UseRelativeLinePragmas = true; - return generator; } diff --git a/Mono.TextTemplating/Mono.TextTemplating.CodeCompilation/CSharpLangVersion.cs b/Mono.TextTemplating/Mono.TextTemplating.CodeCompilation/CSharpLangVersion.cs index 36b3c00..91343e2 100644 --- a/Mono.TextTemplating/Mono.TextTemplating.CodeCompilation/CSharpLangVersion.cs +++ b/Mono.TextTemplating/Mono.TextTemplating.CodeCompilation/CSharpLangVersion.cs @@ -22,5 +22,6 @@ enum CSharpLangVersion v10_0, v11_0, v12_0, + v13_0, Latest = 1024 // make sure value doesn't change as we add new C# versions } diff --git a/Mono.TextTemplating/Mono.TextTemplating.CodeCompilation/CSharpLangVersionHelper.cs b/Mono.TextTemplating/Mono.TextTemplating.CodeCompilation/CSharpLangVersionHelper.cs index 0339575..c1f755b 100644 --- a/Mono.TextTemplating/Mono.TextTemplating.CodeCompilation/CSharpLangVersionHelper.cs +++ b/Mono.TextTemplating/Mono.TextTemplating.CodeCompilation/CSharpLangVersionHelper.cs @@ -48,6 +48,7 @@ public static bool IsLangVersionArg (string arg) => //https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history public static CSharpLangVersion FromNetCoreSdkVersion (SemVersion sdkVersion) => sdkVersion switch { + { Major: 9 } => CSharpLangVersion.v13_0, { Major: 8 } => CSharpLangVersion.v12_0, { Major: 7 } => CSharpLangVersion.v11_0, { Major: 6 } => CSharpLangVersion.v10_0, @@ -73,6 +74,7 @@ public static CSharpLangVersion FromNetCoreSdkVersion (SemVersion sdkVersion) CSharpLangVersion.v10_0 => "10.0", CSharpLangVersion.v11_0 => "11.0", CSharpLangVersion.v12_0 => "12.0", + CSharpLangVersion.v13_0 => "13.0", CSharpLangVersion.Latest => "latest", _ => throw new ArgumentException ($"Not a valid value: '{version}'", nameof (version)) }; diff --git a/Mono.TextTemplating/Mono.TextTemplating.csproj b/Mono.TextTemplating/Mono.TextTemplating.csproj index 25aab18..b1188a8 100644 --- a/Mono.TextTemplating/Mono.TextTemplating.csproj +++ b/Mono.TextTemplating/Mono.TextTemplating.csproj @@ -24,10 +24,7 @@ - - - - + diff --git a/Mono.TextTemplating/Mono.TextTemplating/TemplateSettings.cs b/Mono.TextTemplating/Mono.TextTemplating/TemplateSettings.cs index 769285f..7e69276 100644 --- a/Mono.TextTemplating/Mono.TextTemplating/TemplateSettings.cs +++ b/Mono.TextTemplating/Mono.TextTemplating/TemplateSettings.cs @@ -69,6 +69,12 @@ public TemplateSettings () public string GetFullName () => string.IsNullOrEmpty (Namespace) ? Name : Namespace + "." + Name; internal CodeGenerationOptions CodeGenerationOptions { get; } = new CodeGenerationOptions (); + + /// + /// Base directory for calculation of relative line pragmas. + /// Internal until we clean up the settings API. + /// + internal string RelativeLinePragmasBaseDirectory { get; set; } } public class CustomDirective diff --git a/Mono.TextTemplating/Mono.TextTemplating/TemplatingEngine.CodeGeneration.cs b/Mono.TextTemplating/Mono.TextTemplating/TemplatingEngine.CodeGeneration.cs index 2fdcf8f..72c7949 100644 --- a/Mono.TextTemplating/Mono.TextTemplating/TemplatingEngine.CodeGeneration.cs +++ b/Mono.TextTemplating/Mono.TextTemplating/TemplatingEngine.CodeGeneration.cs @@ -63,7 +63,16 @@ public static CodeCompileUnit GenerateCompileUnit (ITextTemplatingEngineHost hos static void GenerateTransformMethod (CodeTypeDeclaration templateType, TemplateSettings settings, ParsedTemplate pt, string templateFile, bool isOverride) { - string baseDirectory = Path.GetDirectoryName (templateFile); + string pragmasRelativeToDirectory = null; + + if (settings.RelativeLinePragmas) { + if (!string.IsNullOrEmpty (settings.RelativeLinePragmasBaseDirectory)) { + pragmasRelativeToDirectory = Path.GetFullPath (settings.RelativeLinePragmasBaseDirectory); + } + if (pragmasRelativeToDirectory is null && templateFile is not null) { + pragmasRelativeToDirectory = Path.GetDirectoryName (Path.GetFullPath (templateFile)); + } + } var transformMeth = Declare.Method ("TransformText").Returns ().AsVirtual (); @@ -87,16 +96,16 @@ static void GenerateTransformMethod (CodeTypeDeclaration templateType, TemplateS CodeStatement st = null; CodeLinePragma location = null; if (!settings.NoLinePragmas) { - var f = seg.StartLocation.FileName ?? templateFile; - if (!string.IsNullOrEmpty (f)) { - // FIXME: we need to know where the output file will be to make this work properly - if (settings.RelativeLinePragmas) { - f = FileUtil.AbsoluteToRelativePath (baseDirectory, f); - } else { - f = Path.GetFullPath (f); + var filename = seg.StartLocation.FileName ?? templateFile; + if (!string.IsNullOrEmpty (filename)) { + if (!settings.RelativeLinePragmas) { + filename = Path.GetFileName (filename); + } else if (pragmasRelativeToDirectory is not null) { + filename = Path.GetFullPath (filename); + filename = FileUtil.AbsoluteToRelativePath (pragmasRelativeToDirectory, filename); } } - location = new CodeLinePragma (f, seg.StartLocation.Line); + location = new CodeLinePragma (filename, seg.StartLocation.Line); } switch (seg.Type) { case SegmentType.Block: diff --git a/Mono.TextTemplating/package/Mono.TextTemplating.targets b/Mono.TextTemplating/package/Mono.TextTemplating.targets index 53f0035..2c9ce7e 100644 --- a/Mono.TextTemplating/package/Mono.TextTemplating.targets +++ b/Mono.TextTemplating/package/Mono.TextTemplating.targets @@ -1,6 +1,18 @@ - + + <_Mono_TextTemplating_Warn_Compat_Tfm + Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'netcoreapp2.0')) AND + !$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0'))"> + >net6.0 + <_Mono_TextTemplating_Warn_Compat_Tfm + Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net461')) AND + !$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net462'))" + >net462 + + diff --git a/Mono.TextTemplating/package/_._ b/Mono.TextTemplating/package/_._ deleted file mode 100644 index e69de29..0000000