-
Notifications
You must be signed in to change notification settings - Fork 2
/
PreSharpGenerator.cs
167 lines (130 loc) · 6.42 KB
/
PreSharpGenerator.cs
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.CSharp;
internal sealed partial class PreSharpGenerator : MarshalByRefObject {
private readonly List<string> references = new List<string>();
public IEnumerable<string> References {
get { return references; }
}
public PreSharpGenerator() {
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
int commaPos = args.Name.IndexOf(",");
string assemblyName = commaPos == -1 ? args.Name : args.Name.Substring(0, commaPos);
string path = references.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p) == assemblyName);
if (path != null) {
return Assembly.LoadFrom(path);
} else {
return null;
}
};
}
public void AddReference(string reference) {
references.Add(reference);
}
private Logger logger;
private bool debugMode;
private IEnumerable<string> dependencyPaths;
private string conditionalCompilationSymbols;
private string absoluteOutputDir;
public void Init(bool debugMode, Logger logger, IEnumerable<string> dependencyPaths, string conditionalCompilationSymbols, string absoluteOutputDir) {
this.debugMode = debugMode;
this.logger = logger;
this.dependencyPaths = dependencyPaths;
this.conditionalCompilationSymbols = conditionalCompilationSymbols;
this.absoluteOutputDir = absoluteOutputDir;
}
private static readonly CSharpCodeProvider codeProvider =
new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", (AssemblyUtils.GetCLRVersion(typeof(String)).Major >= 4) ? "v4.0" : "v3.5" } });
public bool GenerateLibraryAssemblyFromTemplateLibraryFiles(IEnumerable<string> templateLibraryFiles,
string outputAssemblyPath,
List<string> compileGeneratedFiles) {
List<string> processedTemplateLibraryFiles = new List<string>();
processInplaceFiles(templateLibraryFiles, (filename, content) => {
string processedTemplateLibraryFile;
if (content.Contains("PRESHARP_FILE_IS_TEMPLATE_LIBRARY")) {
processedTemplateLibraryFile = filename + ".PreSharpDebug.cs";
File.WriteAllText(processedTemplateLibraryFile, content.Replace("PRESHARP_FILE_IS_TEMPLATE_LIBRARY", "true"));
logger.LogMessage("Generated debug file '" + processedTemplateLibraryFile + "'.");
} else {
processedTemplateLibraryFile = filename;
}
processedTemplateLibraryFiles.Add(processedTemplateLibraryFile);
if (debugMode) {
compileGeneratedFiles.Add(processedTemplateLibraryFile);
}
});
CompilerParameters compilerOptions = new CompilerParameters();
compilerOptions.GenerateInMemory = false;
compilerOptions.GenerateExecutable = false;
compilerOptions.OutputAssembly = outputAssemblyPath;
compilerOptions.IncludeDebugInformation = true;
compilerOptions.CompilerOptions = "/define:" + conditionalCompilationSymbols;
foreach (string reference in references) {
compilerOptions.ReferencedAssemblies.Add(reference);
}
CompilerResults results = codeProvider.CompileAssemblyFromFile(compilerOptions, processedTemplateLibraryFiles.ToArray());
foreach (CompilerError error in results.Errors) {
if (error.IsWarning) {
logger.LogWarning(error.FileName, error.ErrorNumber, error.ErrorText, error.Line, error.Column);
} else {
logger.LogError(error.FileName, error.ErrorNumber, error.ErrorText, error.Line, error.Column);
}
}
return results.Errors.Count == 0;
}
public void ProcessInplaceFiles(IEnumerable<string> inPlaceFiles, List<string> compileGeneratedFiles) {
processInplaceFiles(inPlaceFiles, (file, content) => {
compileGeneratedFiles.Add(file);
});
}
private void processInplaceFiles(IEnumerable<string> inPlaceFiles, Action<string, string> fileProcessed) {
if (inPlaceFiles != null) {
foreach (string inPlaceFile in inPlaceFiles) {
string[] lines;
try {
lines = File.ReadAllLines(inPlaceFile);
} catch {
logger.LogError(inPlaceFile, null, "Error reading file '" + inPlaceFile + "'", 0, 0);
continue;
}
string output = processTemplateRegions(lines, inPlaceFile);
if (string.Join(Environment.NewLine, lines) + Environment.NewLine != output) {
File.WriteAllText(inPlaceFile, output);
}
fileProcessed(inPlaceFile, output);
}
}
}
public void ProcessTemplateFiles(IEnumerable<string> templateFiles,
IEnumerable<string> templateIncludeFiles,
List<string> compileGeneratedFiles,
List<string> embeddedResourceGeneratedFiles) {
references.Add(Assembly.GetExecutingAssembly().Location);
if (templateFiles != null) {
foreach (string templateFile in templateFiles) {
string templateFileCode;
try {
templateFileCode = File.ReadAllText(templateFile);
} catch {
logger.LogError(templateFile, null, "Error reading file '" + templateFile + "'", 0, 0);
continue;
}
processTemplateFile(templateFile, templateFileCode, templateIncludeFiles, compileGeneratedFiles, embeddedResourceGeneratedFiles);
if (debugMode) {
compileGeneratedFiles.Add(templateFile);
}
}
if (debugMode) {
foreach (var templateIncludeFile in templateIncludeFiles) {
compileGeneratedFiles.Add(templateIncludeFile);
}
}
}
}
}