-
Notifications
You must be signed in to change notification settings - Fork 869
Expand file tree
/
Copy pathProjectCracker.fs
More file actions
130 lines (103 loc) · 5.06 KB
/
Copy pathProjectCracker.fs
File metadata and controls
130 lines (103 loc) · 5.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
namespace FSharp.Compiler.SourceCodeServices
#if !NETSTANDARD1_6
open System.Runtime.Serialization.Json
open System.Runtime
open System.Diagnostics
#endif
open System.Text
open System.IO
open System
open System.Xml
module Utils =
let Convert loadedTimeStamp (originalOpts: ProjectCrackerTool.ProjectOptions) =
let logMap = ref Map.empty
let rec convertProject (opts: ProjectCrackerTool.ProjectOptions) =
if not (isNull opts.Error) then failwith opts.Error
let referencedProjects() = Array.map (fun (a, b) -> a,convertProject b) opts.ReferencedProjectOptions
let sourceFiles, otherOptions =
opts.Options
|> Array.partition (fun x ->
let extension = Path.GetExtension(x).ToLower()
x.IndexOfAny(Path.GetInvalidPathChars()) = -1
&& (extension = ".fs" || extension = ".fsi"))
let sepChar = Path.DirectorySeparatorChar
let sourceFiles = sourceFiles |> Array.map (fun x ->
match sepChar with
| '\\' -> x.Replace('/', '\\')
| '/' -> x.Replace('\\', '/')
| _ -> x
)
logMap := Map.add opts.ProjectFile opts.LogOutput !logMap
{ ProjectFileName = opts.ProjectFile
ProjectId = None
SourceFiles = sourceFiles
OtherOptions = otherOptions
ReferencedProjects = referencedProjects()
IsIncompleteTypeCheckEnvironment = false
UseScriptResolutionRules = false
LoadTime = loadedTimeStamp
UnresolvedReferences = None
OriginalLoadReferences = []
ExtraProjectInfo = None
Stamp = None }
convertProject originalOpts, !logMap
type ProjectCracker =
static member GetProjectOptionsFromProjectFileLogged(projectFileName : string, ?properties : (string * string) list, ?loadedTimeStamp, ?enableLogging) =
let loadedTimeStamp = defaultArg loadedTimeStamp DateTime.MaxValue // Not 'now', we don't want to force reloading
let properties = defaultArg properties []
let enableLogging = defaultArg enableLogging true
#if NETSTANDARD1_6
let arguments = [|
yield projectFileName
yield enableLogging.ToString()
for k, v in properties do
yield k
yield v
|]
let ret, opts = FSharp.Compiler.SourceCodeServices.ProjectCrackerTool.ProjectCrackerTool.crackOpen arguments
ignore ret
#else
let arguments = new StringBuilder()
arguments.Append('"').Append(projectFileName).Append('"') |> ignore
arguments.Append(' ').Append(enableLogging.ToString()) |> ignore
for k, v in properties do
arguments.Append(' ').Append(k).Append(' ').Append(v) |> ignore
let codebase = Path.GetDirectoryName(Uri(typeof<ProjectCracker>.Assembly.CodeBase).LocalPath)
let crackerFilename = Path.Combine(codebase,"FSharp.Compiler.Service.ProjectCrackerTool.exe")
if not (File.Exists crackerFilename) then
failwithf "ProjectCracker exe not found at: %s it must be next to the ProjectCracker dll." crackerFilename
let p = new System.Diagnostics.Process()
p.StartInfo.FileName <- crackerFilename
p.StartInfo.Arguments <- arguments.ToString()
p.StartInfo.UseShellExecute <- false
p.StartInfo.CreateNoWindow <- true
p.StartInfo.RedirectStandardOutput <- true
p.StartInfo.RedirectStandardError <- true
let sbOut = StringBuilder()
let sbErr = StringBuilder()
p.ErrorDataReceived.AddHandler(fun _ a -> sbErr.AppendLine a.Data |> ignore)
p.OutputDataReceived.AddHandler(fun _ a -> sbOut.AppendLine a.Data |> ignore)
ignore <| p.Start()
p.EnableRaisingEvents <- true
p.BeginOutputReadLine()
p.BeginErrorReadLine()
p.WaitForExit()
let crackerOut = sbOut.ToString()
let crackerErr = sbErr.ToString()
let opts =
try
let ser = new DataContractJsonSerializer(typeof<ProjectCrackerTool.ProjectOptions>)
let stringBytes = Encoding.Unicode.GetBytes crackerOut
use ms = new MemoryStream(stringBytes)
ser.ReadObject(ms) :?> ProjectCrackerTool.ProjectOptions
with
exn ->
raise (Exception(sprintf "error parsing ProjectCrackerTool output, stdoutput was:\n%s\n\nstderr was:\n%s" crackerOut crackerErr, exn))
#endif
Utils.Convert loadedTimeStamp opts
static member GetProjectOptionsFromProjectFile(projectFileName : string, ?properties : (string * string) list, ?loadedTimeStamp) =
fst (ProjectCracker.GetProjectOptionsFromProjectFileLogged(
projectFileName,
?properties=properties,
?loadedTimeStamp=loadedTimeStamp,
enableLogging=false))