forked from scriptcs/scriptcs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFilePreProcessor.cs
More file actions
147 lines (122 loc) · 4.84 KB
/
Copy pathFilePreProcessor.cs
File metadata and controls
147 lines (122 loc) · 4.84 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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System;
using System.Collections.Generic;
using System.Linq;
namespace ScriptCs
{
public class FilePreProcessor : IFilePreProcessor
{
private const string LoadString = "#load ";
private const string UsingString = "using ";
private const string RString = "#r ";
protected readonly IFileSystem _fileSystem;
public FilePreProcessor(IFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
public string ProcessFile(string path)
{
var entryFile = _fileSystem.ReadFileLines(path);
var usings = new List<string>();
var rs = new List<string>();
var loads = new List<string>();
var parsed = ParseFile(path, entryFile, ref usings, ref rs, ref loads);
var result = GenerateRs(rs);
if (!string.IsNullOrWhiteSpace(result))
{
result += _fileSystem.NewLine;
}
result += GenerateUsings(usings);
if (!string.IsNullOrWhiteSpace(result))
{
result += _fileSystem.NewLine;
}
result += parsed;
return result;
}
protected virtual string GenerateUsings(ICollection<string> usingLines)
{
return string.Join(_fileSystem.NewLine, usingLines.Distinct());
}
protected virtual string GenerateRs(ICollection<string> rLines)
{
return string.Join(_fileSystem.NewLine, rLines.Distinct());
}
private string ParseFile(string path, IEnumerable<string> file, ref List<string> usings, ref List<string> rs, ref List<string> loads)
{
var fileList = file.ToList();
var firstCode = fileList.FindIndex(l => IsNonDirectiveLine(l));
var firstBody = fileList.FindIndex(l => IsNonDirectiveLine(l) && !IsUsingLine(l));
// add #line before the actual code begins
// +1 because we are in a zero indexed list, but line numbers are 1 indexed
// we need to keep the original position of the actual line
if (firstBody != -1)
{
fileList.Insert(firstBody, string.Format(@"#line {0} ""{1}""", firstBody + 1, path));
}
for (var i = 0; i < fileList.Count; i++)
{
var line = fileList[i];
if (IsUsingLine(line))
{
usings.Add(line);
}
else if (IsRLine(line))
{
if (i < firstCode)
{
rs.Add(line);
}
else
{
fileList[i] = string.Empty;
}
}
else if (IsLoadLine(line))
{
if ((i < firstCode || firstCode < 0) && !loads.Contains(line))
{
var filepath = line.Trim(' ').Replace(LoadString, string.Empty).Replace("\"", string.Empty).Replace(";", string.Empty);
var filecontent = _fileSystem.IsPathRooted(filepath)
? _fileSystem.ReadFileLines(filepath)
: _fileSystem.ReadFileLines(_fileSystem.CurrentDirectory + @"\" + filepath);
if (filecontent != null)
{
loads.Add(line);
var parsed = ParseFile(filepath, filecontent, ref usings, ref rs, ref loads);
fileList[i] =/* string.Format("//{0}{1}", filepath, _fileSystem.NewLine) + */parsed;
}
}
else
{
fileList[i] = string.Empty;
}
}
}
var result = string.Join(_fileSystem.NewLine, fileList.Where(line => !IsUsingLine(line) && !IsRLine(line)));
return result;
}
private static bool IsNonDirectiveLine(string line)
{
return !IsRLine(line) && !IsLoadLine(line) && line.Trim() != string.Empty;
}
private static bool IsUsingLine(string line)
{
return line.TrimStart(' ').StartsWith(UsingString) && !line.Contains("{") && line.Contains(";");
}
private static bool IsRLine(string line)
{
return line.TrimStart(' ').StartsWith(RString);
}
private static bool IsLoadLine(string line)
{
return line.TrimStart(' ').StartsWith(LoadString);
}
private enum ParsingStatus
{
ForbidReferences,
ForbidLoads,
ForbidUsings,
NoRestrictions
}
}
}