未验证 提交 823f7d5c 编写于 作者: T Theodore Tsirpanis 提交者: GitHub

Use MSBuild's logging facilities instead of writing to console. (#13896)

* Use MSBuild's logging facilities instead of writing to console.

* Changing usage of WriteCodeFragment in tests

* Applying cleaner formatting
Co-authored-by: NTomas Grosup <tomasgrosup@microsoft.com>
上级 05201993
...@@ -10,14 +10,20 @@ open System.Xml.Linq ...@@ -10,14 +10,20 @@ open System.Xml.Linq
open Microsoft.Build.Framework open Microsoft.Build.Framework
open Microsoft.Build.Utilities open Microsoft.Build.Utilities
type FSharpEmbedResXSource() = type FSharpEmbedResXSource() as this =
let mutable _buildEngine: IBuildEngine MaybeNull = null inherit Task()
let mutable _hostObject: ITaskHost MaybeNull = null
let mutable _embeddedText: ITaskItem[] = [||] let mutable _embeddedText: ITaskItem[] = [||]
let mutable _generatedSource: ITaskItem[] = [||] let mutable _generatedSource: ITaskItem[] = [||]
let mutable _outputPath: string = "" let mutable _outputPath: string = ""
let mutable _targetFramework: string = "" let mutable _targetFramework: string = ""
let failTask fmt =
Printf.ksprintf
(fun msg ->
this.Log.LogError msg
raise TaskFailed)
fmt
let boilerplate = let boilerplate =
@"// <auto-generated> @"// <auto-generated>
...@@ -36,7 +42,7 @@ module internal {1} = ...@@ -36,7 +42,7 @@ module internal {1} =
let generateSource (resx: string) (fullModuleName: string) (generateLegacy: bool) (generateLiteral: bool) = let generateSource (resx: string) (fullModuleName: string) (generateLegacy: bool) (generateLiteral: bool) =
try try
let printMessage = printfn "FSharpEmbedResXSource: %s" let printMessage fmt = Printf.ksprintf this.Log.LogMessage fmt
let justFileName = Path.GetFileNameWithoutExtension(resx) let justFileName = Path.GetFileNameWithoutExtension(resx)
let sourcePath = Path.Combine(_outputPath, justFileName + ".fs") let sourcePath = Path.Combine(_outputPath, justFileName + ".fs")
...@@ -46,7 +52,7 @@ module internal {1} = ...@@ -46,7 +52,7 @@ module internal {1} =
&& File.Exists(sourcePath) && File.Exists(sourcePath)
&& File.GetLastWriteTimeUtc(resx) <= File.GetLastWriteTimeUtc(sourcePath) && File.GetLastWriteTimeUtc(resx) <= File.GetLastWriteTimeUtc(sourcePath)
then then
printMessage (sprintf "Skipping generation: '%s' since it is up-to-date." sourcePath) printMessage "Skipping generation: '%s' since it is up-to-date." sourcePath
Some(sourcePath) Some(sourcePath)
else else
let namespaceName, moduleName = let namespaceName, moduleName =
...@@ -63,7 +69,7 @@ module internal {1} = ...@@ -63,7 +69,7 @@ module internal {1} =
|| _targetFramework.StartsWith("netcoreapp1.") || _targetFramework.StartsWith("netcoreapp1.")
) )
printMessage (sprintf "Generating code for target framework %s" _targetFramework) printMessage "Generating code for target framework %s" _targetFramework
let sb = let sb =
StringBuilder() StringBuilder()
...@@ -72,7 +78,7 @@ module internal {1} = ...@@ -72,7 +78,7 @@ module internal {1} =
if generateGetObject then if generateGetObject then
sb.AppendLine(boilerplateGetObject) |> ignore sb.AppendLine(boilerplateGetObject) |> ignore
printMessage <| sprintf "Generating: %s" sourcePath printMessage "Generating: %s" sourcePath
let body = let body =
let xname = XName.op_Implicit let xname = XName.op_Implicit
...@@ -82,12 +88,12 @@ module internal {1} = ...@@ -82,12 +88,12 @@ module internal {1} =
(fun (sb: StringBuilder) (node: XElement) -> (fun (sb: StringBuilder) (node: XElement) ->
let name = let name =
match node.Attribute(xname "name") with match node.Attribute(xname "name") with
| null -> failwith (sprintf "Missing resource name on element '%s'" (node.ToString())) | null -> failTask "Missing resource name on element '%O'" node
| attr -> attr.Value | attr -> attr.Value
let docComment = let docComment =
match node.Elements(xname "value").FirstOrDefault() with match node.Elements(xname "value").FirstOrDefault() with
| null -> failwith <| sprintf "Missing resource value for '%s'" name | null -> failTask "Missing resource value for '%s'" name
| element -> element.Value.Trim() | element -> element.Value.Trim()
let identifier = let identifier =
...@@ -118,7 +124,7 @@ module internal {1} = ...@@ -118,7 +124,7 @@ module internal {1} =
sb sb
File.WriteAllText(sourcePath, body.ToString()) File.WriteAllText(sourcePath, body.ToString())
printMessage <| sprintf "Done: %s" sourcePath printMessage "Done: %s" sourcePath
Some(sourcePath) Some(sourcePath)
with e -> with e ->
printf "An exception occurred when processing '%s'\n%s" resx (e.ToString()) printf "An exception occurred when processing '%s'\n%s" resx (e.ToString())
...@@ -141,16 +147,8 @@ module internal {1} = ...@@ -141,16 +147,8 @@ module internal {1} =
[<Output>] [<Output>]
member _.GeneratedSource = _generatedSource member _.GeneratedSource = _generatedSource
interface ITask with override this.Execute() =
member _.BuildEngine try
with get () = _buildEngine
and set (value) = _buildEngine <- value
member _.HostObject
with get () = _hostObject
and set (value) = _hostObject <- value
member this.Execute() =
let getBooleanMetadata (metadataName: string) (defaultValue: bool) (item: ITaskItem) = let getBooleanMetadata (metadataName: string) (defaultValue: bool) (item: ITaskItem) =
match item.GetMetadata(metadataName) with match item.GetMetadata(metadataName) with
| value when String.IsNullOrWhiteSpace(value) -> defaultValue | value when String.IsNullOrWhiteSpace(value) -> defaultValue
...@@ -158,7 +156,7 @@ module internal {1} = ...@@ -158,7 +156,7 @@ module internal {1} =
match value.ToLowerInvariant() with match value.ToLowerInvariant() with
| "true" -> true | "true" -> true
| "false" -> false | "false" -> false
| _ -> failwith (sprintf "Expected boolean value for '%s' found '%s'" metadataName value) | _ -> failTask "Expected boolean value for '%s' found '%s'" metadataName value
let mutable success = true let mutable success = true
...@@ -181,4 +179,6 @@ module internal {1} = ...@@ -181,4 +179,6 @@ module internal {1} =
|] |]
_generatedSource <- generatedSource _generatedSource <- generatedSource
success success && not this.Log.HasLoggedErrors
with TaskFailed ->
false
...@@ -6,24 +6,32 @@ open System.IO ...@@ -6,24 +6,32 @@ open System.IO
open Microsoft.Build.Framework open Microsoft.Build.Framework
open Microsoft.Build.Utilities open Microsoft.Build.Utilities
type FSharpEmbedResourceText() = /// A special exception that when thrown signifies that
let mutable _buildEngine: IBuildEngine MaybeNull = null /// the task should end with failure. It is assumed that
let mutable _hostObject: ITaskHost MaybeNull = null /// the task has already emitted the error message.
exception TaskFailed
type FSharpEmbedResourceText() as this =
inherit Task()
let mutable _embeddedText: ITaskItem[] = [||] let mutable _embeddedText: ITaskItem[] = [||]
let mutable _generatedSource: ITaskItem[] = [||] let mutable _generatedSource: ITaskItem[] = [||]
let mutable _generatedResx: ITaskItem[] = [||] let mutable _generatedResx: ITaskItem[] = [||]
let mutable _outputPath: string = "" let mutable _outputPath: string = ""
let PrintErr (fileName, line, msg) = let PrintErr (fileName, line, msg) =
printfn "%s(%d): error : %s" fileName line msg this.Log.LogError(null, null, null, fileName, line, 0, 0, 0, msg, Array.empty)
let Err (fileName, line, msg) = let Err (fileName, line, msg) =
PrintErr(fileName, line, msg) PrintErr(fileName, line, msg)
printfn "Note that the syntax of each line is one of these three alternatives:"
printfn "# comment" let hint =
printfn "ident,\"string\"" "Note that the syntax of each line is one of these three alternatives:
printfn "errNum,ident,\"string\"" # comment
failwith (sprintf "there were errors in the file '%s'" fileName) ident,\"string\"
errNum,ident,\"string\""
this.Log.LogMessage(MessageImportance.High, hint)
raise TaskFailed
let xmlBoilerPlateString = let xmlBoilerPlateString =
@"<?xml version=""1.0"" encoding=""utf-8""?> @"<?xml version=""1.0"" encoding=""utf-8""?>
...@@ -192,7 +200,7 @@ type FSharpEmbedResourceText() = ...@@ -192,7 +200,7 @@ type FSharpEmbedResourceText() =
if s.StartsWith "\"" && s.EndsWith "\"" then if s.StartsWith "\"" && s.EndsWith "\"" then
s.Substring(1, s.Length - 2) s.Substring(1, s.Length - 2)
else else
failwith "error message string should be quoted" Err(null, 0, "error message string should be quoted")
let ParseLine fileName lineNum (txt: string) = let ParseLine fileName lineNum (txt: string) =
let mutable errNum = None let mutable errNum = None
...@@ -361,8 +369,7 @@ open Printf ...@@ -361,8 +369,7 @@ open Printf
let generateResxAndSource (fileName: string) = let generateResxAndSource (fileName: string) =
try try
let printMessage message = let printMessage fmt = Printf.ksprintf this.Log.LogMessage fmt
printfn "FSharpEmbedResourceText: %s" message
let justFileName = Path.GetFileNameWithoutExtension(fileName) // .txt let justFileName = Path.GetFileNameWithoutExtension(fileName) // .txt
...@@ -391,35 +398,33 @@ open Printf ...@@ -391,35 +398,33 @@ open Printf
&& (File.GetLastWriteTimeUtc(fileName) <= File.GetLastWriteTimeUtc(outXmlFileName)) && (File.GetLastWriteTimeUtc(fileName) <= File.GetLastWriteTimeUtc(outXmlFileName))
if condition5 then if condition5 then
printMessage (sprintf "Skipping generation of %s and %s from %s since up-to-date" outFileName outXmlFileName fileName) printMessage "Skipping generation of %s and %s from %s since up-to-date" outFileName outXmlFileName fileName
Some(fileName, outFileName, outXmlFileName) Some(fileName, outFileName, outXmlFileName)
else else
printMessage ( printMessage
sprintf "Generating %s and %s from %s, because condition %d is false, see FSharpEmbedResourceText.fs in the F# source"
"Generating %s and %s from %s, because condition %d is false, see FSharpEmbedResourceText.fs in the F# source" outFileName
outFileName outXmlFileName
outXmlFileName fileName
fileName (if not condition1 then 1
(if not condition1 then 1 elif not condition2 then 2
elif not condition2 then 2 elif not condition3 then 3
elif not condition3 then 3 elif not condition4 then 4
elif not condition4 then 4 else 5)
else 5)
) printMessage "Reading %s" fileName
printMessage (sprintf "Reading %s" fileName)
let lines = let lines =
File.ReadAllLines(fileName) File.ReadAllLines(fileName)
|> Array.mapi (fun i s -> i, s) // keep line numbers |> Array.mapi (fun i s -> i, s) // keep line numbers
|> Array.filter (fun (i, s) -> not (s.StartsWith "#")) // filter out comments |> Array.filter (fun (i, s) -> not (s.StartsWith "#")) // filter out comments
printMessage (sprintf "Parsing %s" fileName) printMessage "Parsing %s" fileName
let stringInfos = lines |> Array.map (fun (i, s) -> ParseLine fileName i s) let stringInfos = lines |> Array.map (fun (i, s) -> ParseLine fileName i s)
// now we have array of (lineNum, ident, str, holes, netFormatString) // str has %d, netFormatString has {0} // now we have array of (lineNum, ident, str, holes, netFormatString) // str has %d, netFormatString has {0}
printMessage (sprintf "Validating %s" fileName) printMessage "Validating %s" fileName
// validate that all the idents are unique // validate that all the idents are unique
let allIdents = new System.Collections.Generic.Dictionary<string, int>() let allIdents = new System.Collections.Generic.Dictionary<string, int>()
...@@ -436,7 +441,7 @@ open Printf ...@@ -436,7 +441,7 @@ open Printf
allIdents.Add(ident, line) allIdents.Add(ident, line)
printMessage (sprintf "Validating uniqueness of %s" fileName) printMessage "Validating uniqueness of %s" fileName
// validate that all the strings themselves are unique // validate that all the strings themselves are unique
let allStrs = new System.Collections.Generic.Dictionary<string, (int * string)>() let allStrs = new System.Collections.Generic.Dictionary<string, (int * string)>()
...@@ -456,7 +461,7 @@ open Printf ...@@ -456,7 +461,7 @@ open Printf
allStrs.Add(str, (line, ident)) allStrs.Add(str, (line, ident))
printMessage (sprintf "Generating %s" outFileName) printMessage "Generating %s" outFileName
use outStream = File.Create outFileName use outStream = File.Create outFileName
use out = new StreamWriter(outStream) use out = new StreamWriter(outStream)
fprintfn out "// This is a generated file; the original input is '%s'" fileName fprintfn out "// This is a generated file; the original input is '%s'" fileName
...@@ -466,7 +471,7 @@ open Printf ...@@ -466,7 +471,7 @@ open Printf
let theResourceName = justFileName let theResourceName = justFileName
fprintfn out "%s" (StringBoilerPlate theResourceName) fprintfn out "%s" (StringBoilerPlate theResourceName)
printMessage (sprintf "Generating resource methods for %s" outFileName) printMessage "Generating resource methods for %s" outFileName
// gen each resource method // gen each resource method
stringInfos stringInfos
|> Seq.iter (fun (lineNum, (optErrNum, ident), str, holes, netFormatString) -> |> Seq.iter (fun (lineNum, (optErrNum, ident), str, holes, netFormatString) ->
...@@ -520,7 +525,7 @@ open Printf ...@@ -520,7 +525,7 @@ open Printf
justPercentsFromFormatString justPercentsFromFormatString
(actualArgs.ToString())) (actualArgs.ToString()))
printMessage (sprintf "Generating .resx for %s" outFileName) printMessage "Generating .resx for %s" outFileName
fprintfn out "" fprintfn out ""
// gen validation method // gen validation method
fprintfn out " /// Call this method once to validate that all known resources are valid; throws if not" fprintfn out " /// Call this method once to validate that all known resources are valid; throws if not"
...@@ -548,7 +553,7 @@ open Printf ...@@ -548,7 +553,7 @@ open Printf
use outXmlStream = File.Create outXmlFileName use outXmlStream = File.Create outXmlFileName
xd.Save outXmlStream xd.Save outXmlStream
printMessage (sprintf "Done %s" outFileName) printMessage "Done %s" outFileName
Some(fileName, outFileName, outXmlFileName) Some(fileName, outFileName, outXmlFileName)
with e -> with e ->
PrintErr(fileName, 0, sprintf "An exception occurred when processing '%s'\n%s" fileName (e.ToString())) PrintErr(fileName, 0, sprintf "An exception occurred when processing '%s'\n%s" fileName (e.ToString()))
...@@ -570,17 +575,9 @@ open Printf ...@@ -570,17 +575,9 @@ open Printf
[<Output>] [<Output>]
member _.GeneratedResx = _generatedResx member _.GeneratedResx = _generatedResx
interface ITask with override this.Execute() =
member _.BuildEngine
with get () = _buildEngine
and set (value) = _buildEngine <- value
member _.HostObject
with get () = _hostObject
and set (value) = _hostObject <- value
member this.Execute() =
try
let generatedFiles = let generatedFiles =
this.EmbeddedText this.EmbeddedText
|> Array.choose (fun item -> generateResxAndSource item.ItemSpec) |> Array.choose (fun item -> generateResxAndSource item.ItemSpec)
...@@ -609,4 +606,6 @@ open Printf ...@@ -609,4 +606,6 @@ open Printf
_generatedSource <- generatedSource _generatedSource <- generatedSource
_generatedResx <- generatedResx _generatedResx <- generatedResx
generatedResult generatedResult && not this.Log.HasLoggedErrors
with TaskFailed ->
false
...@@ -5,11 +5,10 @@ namespace FSharp.Build ...@@ -5,11 +5,10 @@ namespace FSharp.Build
open System open System
open System.IO open System.IO
open Microsoft.Build.Framework open Microsoft.Build.Framework
open Microsoft.Build.Utilities
type SubstituteText() = type SubstituteText() =
inherit Task()
let mutable _buildEngine: IBuildEngine MaybeNull = null
let mutable _hostObject: ITaskHost MaybeNull = null
let mutable copiedFiles = new ResizeArray<ITaskItem>() let mutable copiedFiles = new ResizeArray<ITaskItem>()
let mutable embeddedResources: ITaskItem[] = [||] let mutable embeddedResources: ITaskItem[] = [||]
...@@ -22,74 +21,65 @@ type SubstituteText() = ...@@ -22,74 +21,65 @@ type SubstituteText() =
[<Output>] [<Output>]
member _.CopiedFiles = copiedFiles.ToArray() member _.CopiedFiles = copiedFiles.ToArray()
interface ITask with override _.Execute() =
member _.BuildEngine copiedFiles.Clear()
with get () = _buildEngine
and set (value) = _buildEngine <- value if not (isNull embeddedResources) then
for item in embeddedResources do
member _.HostObject // Update ITaskItem metadata to point to new location
with get () = _hostObject let sourcePath = item.GetMetadata("FullPath")
and set (value) = _hostObject <- value
let pattern1 = item.GetMetadata("Pattern1")
member _.Execute() = let pattern2 = item.GetMetadata("Pattern2")
copiedFiles.Clear()
// Is there any replacement to do?
if not (isNull embeddedResources) then if not (String.IsNullOrWhiteSpace(pattern1) && String.IsNullOrWhiteSpace(pattern2)) then
for item in embeddedResources do if not (String.IsNullOrWhiteSpace(sourcePath)) then
// Update ITaskItem metadata to point to new location try
let sourcePath = item.GetMetadata("FullPath") let getTargetPathFrom key =
let md = item.GetMetadata(key)
let pattern1 = item.GetMetadata("Pattern1") let path = Path.GetDirectoryName(md)
let pattern2 = item.GetMetadata("Pattern2") let fileName = Path.GetFileName(md)
let target = Path.Combine(path, @"..\resources", fileName)
// Is there any replacement to do? target
if not (String.IsNullOrWhiteSpace(pattern1) && String.IsNullOrWhiteSpace(pattern2)) then
if not (String.IsNullOrWhiteSpace(sourcePath)) then // Copy from the location specified in Identity
try let sourcePath = item.GetMetadata("Identity")
let getTargetPathFrom key =
let md = item.GetMetadata(key) // Copy to the location specified in TargetPath unless no TargetPath is provided, then use Identity
let path = Path.GetDirectoryName(md) let targetPath =
let fileName = Path.GetFileName(md) let identityPath = getTargetPathFrom "Identity"
let target = Path.Combine(path, @"..\resources", fileName) let intermediateTargetPath = item.GetMetadata("IntermediateTargetPath")
if not (String.IsNullOrWhiteSpace(intermediateTargetPath)) then
let fileName = Path.GetFileName(identityPath)
let target = Path.Combine(intermediateTargetPath, fileName)
target target
else
identityPath
// Copy from the location specified in Identity item.ItemSpec <- targetPath
let sourcePath = item.GetMetadata("Identity")
// Copy to the location specified in TargetPath unless no TargetPath is provided, then use Identity
let targetPath =
let identityPath = getTargetPathFrom "Identity"
let intermediateTargetPath = item.GetMetadata("IntermediateTargetPath")
if not (String.IsNullOrWhiteSpace(intermediateTargetPath)) then
let fileName = Path.GetFileName(identityPath)
let target = Path.Combine(intermediateTargetPath, fileName)
target
else
identityPath
item.ItemSpec <- targetPath
// Transform file // Transform file
let mutable contents = File.ReadAllText(sourcePath) let mutable contents = File.ReadAllText(sourcePath)
if not (String.IsNullOrWhiteSpace(pattern1)) then if not (String.IsNullOrWhiteSpace(pattern1)) then
let replacement = item.GetMetadata("Replacement1") let replacement = item.GetMetadata("Replacement1")
contents <- contents.Replace(pattern1, replacement) contents <- contents.Replace(pattern1, replacement)
if not (String.IsNullOrWhiteSpace(pattern2)) then if not (String.IsNullOrWhiteSpace(pattern2)) then
let replacement = item.GetMetadata("Replacement2") let replacement = item.GetMetadata("Replacement2")
contents <- contents.Replace(pattern2, replacement) contents <- contents.Replace(pattern2, replacement)
let directory = Path.GetDirectoryName(targetPath) let directory = Path.GetDirectoryName(targetPath)
if not (Directory.Exists(directory)) then if not (Directory.Exists(directory)) then
Directory.CreateDirectory(directory) |> ignore Directory.CreateDirectory(directory) |> ignore
File.WriteAllText(targetPath, contents) File.WriteAllText(targetPath, contents)
with _ -> with _ ->
() ()
copiedFiles.Add(item) copiedFiles.Add(item)
true true
...@@ -9,14 +9,20 @@ open System.Text ...@@ -9,14 +9,20 @@ open System.Text
open Microsoft.Build.Framework open Microsoft.Build.Framework
open Microsoft.Build.Utilities open Microsoft.Build.Utilities
type WriteCodeFragment() = type WriteCodeFragment() as this =
let mutable _buildEngine: IBuildEngine MaybeNull = null inherit Task()
let mutable _hostObject: ITaskHost MaybeNull = null
let mutable _outputDirectory: ITaskItem MaybeNull = null let mutable _outputDirectory: ITaskItem MaybeNull = null
let mutable _outputFile: ITaskItem MaybeNull = null let mutable _outputFile: ITaskItem MaybeNull = null
let mutable _language: string = "" let mutable _language: string = ""
let mutable _assemblyAttributes: ITaskItem[] = [||] let mutable _assemblyAttributes: ITaskItem[] = [||]
let failTask fmt =
Printf.ksprintf
(fun msg ->
this.Log.LogError msg
raise TaskFailed)
fmt
static let escapeString (str: string) = static let escapeString (str: string) =
let sb = let sb =
str.ToCharArray() str.ToCharArray()
...@@ -37,7 +43,7 @@ type WriteCodeFragment() = ...@@ -37,7 +43,7 @@ type WriteCodeFragment() =
sb.Append("\"").ToString() sb.Append("\"").ToString()
static member GenerateAttribute(item: ITaskItem, language: string) = member _.GenerateAttribute(item: ITaskItem, language: string) =
let attributeName = item.ItemSpec let attributeName = item.ItemSpec
let args = let args =
...@@ -70,7 +76,7 @@ type WriteCodeFragment() = ...@@ -70,7 +76,7 @@ type WriteCodeFragment() =
match Int32.TryParse indexString with match Int32.TryParse indexString with
| (true, index) -> (index, value) | (true, index) -> (index, value)
| (false, _) -> failwith (sprintf "Unable to parse '%s' as an index" indexString)) | (false, _) -> failTask "Unable to parse '%s' as an index" indexString)
|> List.sortBy fst |> List.sortBy fst
// assign ordered parameters to array // assign ordered parameters to array
let orderedParametersArray = let orderedParametersArray =
...@@ -96,7 +102,7 @@ type WriteCodeFragment() = ...@@ -96,7 +102,7 @@ type WriteCodeFragment() =
| "f#" -> sprintf "[<assembly: %s(%s)>]" attributeName args | "f#" -> sprintf "[<assembly: %s(%s)>]" attributeName args
| "c#" -> sprintf "[assembly: %s(%s)]" attributeName args | "c#" -> sprintf "[assembly: %s(%s)]" attributeName args
| "vb" -> sprintf "<Assembly: %s(%s)>" attributeName args | "vb" -> sprintf "<Assembly: %s(%s)>" attributeName args
| _ -> failwith "Language name must be one of F#, C# or VB" | _ -> failTask "Language name must be one of F#, C# or VB"
// adding this property to maintain API equivalence with the MSBuild task // adding this property to maintain API equivalence with the MSBuild task
member _.Language member _.Language
...@@ -116,56 +122,45 @@ type WriteCodeFragment() = ...@@ -116,56 +122,45 @@ type WriteCodeFragment() =
with get () = _outputFile with get () = _outputFile
and set (value) = _outputFile <- value and set (value) = _outputFile <- value
interface ITask with override this.Execute() =
member _.BuildEngine try
with get () = _buildEngine match _outputFile with
and set (value) = _buildEngine <- value | Null -> failTask "Output location must be specified"
| NonNull outputFile ->
member _.HostObject let boilerplate =
with get () = _hostObject match _language.ToLowerInvariant() with
and set (value) = _hostObject <- value | "f#" ->
"// <auto-generated>\n// Generated by the FSharp WriteCodeFragment class.\n// </auto-generated>\nnamespace FSharp\n\nopen System\nopen System.Reflection\n"
member _.Execute() = | "c#" ->
try "// <auto-generated>\n// Generated by the FSharp WriteCodeFragment class.\n// </auto-generated>\n\nusing System;\nusing System.Reflection;"
match _outputFile with | "vb" ->
| Null -> failwith "Output location must be specified" "'------------------------------------------------------------------------------\n' <auto-generated>\n' Generated by the FSharp WriteCodeFragment class.\n' </auto-generated>\n'------------------------------------------------------------------------------\n\nOption Strict Off\nOption Explicit On\n\nImports System\nImports System.Reflection"
| NonNull outputFile -> | _ -> failTask "Language name must be one of F#, C# or VB"
let boilerplate =
match _language.ToLowerInvariant() with let sb = StringBuilder().AppendLine(boilerplate).AppendLine()
| "f#" ->
"// <auto-generated>\n// Generated by the FSharp WriteCodeFragment class.\n// </auto-generated>\nnamespace FSharp\n\nopen System\nopen System.Reflection\n" let code =
| "c#" -> (sb, _assemblyAttributes)
"// <auto-generated>\n// Generated by the FSharp WriteCodeFragment class.\n// </auto-generated>\n\nusing System;\nusing System.Reflection;" ||> Array.fold (fun (sb: StringBuilder) (item: ITaskItem) ->
| "vb" -> sb.AppendLine(this.GenerateAttribute(item, _language.ToLowerInvariant())))
"'------------------------------------------------------------------------------\n' <auto-generated>\n' Generated by the FSharp WriteCodeFragment class.\n' </auto-generated>\n'------------------------------------------------------------------------------\n\nOption Strict Off\nOption Explicit On\n\nImports System\nImports System.Reflection"
| _ -> failwith "Language name must be one of F#, C# or VB" if _language.ToLowerInvariant() = "f#" then
code.AppendLine("do()") |> ignore
let sb = StringBuilder().AppendLine(boilerplate).AppendLine()
let fileName = outputFile.ItemSpec
let code =
(sb, _assemblyAttributes) let outputFileItem =
||> Array.fold (fun (sb: StringBuilder) (item: ITaskItem) -> match _outputDirectory with
sb.AppendLine(WriteCodeFragment.GenerateAttribute(item, _language.ToLowerInvariant()))) | Null -> outputFile
| NonNull outputDirectory ->
if _language.ToLowerInvariant() = "f#" then if Path.IsPathRooted(fileName) then
code.AppendLine("do()") |> ignore outputFile
else
let fileName = outputFile.ItemSpec TaskItem(Path.Combine(outputDirectory.ItemSpec, fileName)) :> ITaskItem
let outputFileItem = let codeText = code.ToString()
match _outputDirectory with File.WriteAllText(fileName, codeText)
| Null -> outputFile _outputFile <- outputFileItem
| NonNull outputDirectory -> not this.Log.HasLoggedErrors
if Path.IsPathRooted(fileName) then with TaskFailed ->
outputFile false
else
TaskItem(Path.Combine(outputDirectory.ItemSpec, fileName)) :> ITaskItem
let codeText = code.ToString()
File.WriteAllText(fileName, codeText)
_outputFile <- outputFileItem
true
with e ->
printf "Error writing code fragment: %s" (e.ToString())
false
...@@ -13,7 +13,7 @@ type WriteCodeFragmentFSharpTests() = ...@@ -13,7 +13,7 @@ type WriteCodeFragmentFSharpTests() =
let verifyAttribute (attributeName:string) (parameters:(string*string) list) (expectedAttributeText:string) = let verifyAttribute (attributeName:string) (parameters:(string*string) list) (expectedAttributeText:string) =
let taskItem = TaskItem(attributeName) let taskItem = TaskItem(attributeName)
parameters |> List.iter (fun (key, value) -> taskItem.SetMetadata(key, value)) parameters |> List.iter (fun (key, value) -> taskItem.SetMetadata(key, value))
let actualAttributeText = WriteCodeFragment.GenerateAttribute (taskItem :> ITaskItem, "f#") let actualAttributeText = (new WriteCodeFragment()).GenerateAttribute (taskItem :> ITaskItem, "f#")
let fullExpectedAttributeText = "[<assembly: " + expectedAttributeText + ">]" let fullExpectedAttributeText = "[<assembly: " + expectedAttributeText + ">]"
Assert.AreEqual(fullExpectedAttributeText, actualAttributeText) Assert.AreEqual(fullExpectedAttributeText, actualAttributeText)
...@@ -43,7 +43,7 @@ type WriteCodeFragmentCSharpTests() = ...@@ -43,7 +43,7 @@ type WriteCodeFragmentCSharpTests() =
let verifyAttribute (attributeName:string) (parameters:(string*string) list) (expectedAttributeText:string) = let verifyAttribute (attributeName:string) (parameters:(string*string) list) (expectedAttributeText:string) =
let taskItem = TaskItem(attributeName) let taskItem = TaskItem(attributeName)
parameters |> List.iter (fun (key, value) -> taskItem.SetMetadata(key, value)) parameters |> List.iter (fun (key, value) -> taskItem.SetMetadata(key, value))
let actualAttributeText = WriteCodeFragment.GenerateAttribute (taskItem :> ITaskItem, "c#") let actualAttributeText = (new WriteCodeFragment()).GenerateAttribute (taskItem :> ITaskItem, "c#")
let fullExpectedAttributeText = "[assembly: " + expectedAttributeText + "]" let fullExpectedAttributeText = "[assembly: " + expectedAttributeText + "]"
Assert.AreEqual(fullExpectedAttributeText, actualAttributeText) Assert.AreEqual(fullExpectedAttributeText, actualAttributeText)
...@@ -75,7 +75,7 @@ type WriteCodeFragmentVisualBasicTests() = ...@@ -75,7 +75,7 @@ type WriteCodeFragmentVisualBasicTests() =
let verifyAttribute (attributeName:string) (parameters:(string*string) list) (expectedAttributeText:string) = let verifyAttribute (attributeName:string) (parameters:(string*string) list) (expectedAttributeText:string) =
let taskItem = TaskItem(attributeName) let taskItem = TaskItem(attributeName)
parameters |> List.iter (fun (key, value) -> taskItem.SetMetadata(key, value)) parameters |> List.iter (fun (key, value) -> taskItem.SetMetadata(key, value))
let actualAttributeText = WriteCodeFragment.GenerateAttribute (taskItem :> ITaskItem, "vb") let actualAttributeText = (new WriteCodeFragment()).GenerateAttribute (taskItem :> ITaskItem, "vb")
let fullExpectedAttributeText = "<Assembly: " + expectedAttributeText + ">" let fullExpectedAttributeText = "<Assembly: " + expectedAttributeText + ">"
Assert.AreEqual(fullExpectedAttributeText, actualAttributeText) Assert.AreEqual(fullExpectedAttributeText, actualAttributeText)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册