Skip to content

Commit 431958d

Browse files
authored
Merge pull request #17 from EmbarkStudios/webbju/fix-unit-tests
Strict-mode support and unit-test fixes.
2 parents 8de1df5 + 85df552 commit 431958d

13 files changed

+116
-102
lines changed

ServerCodeExciser/ServerCodeExciser.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,13 @@ public sealed class Settings : CommandSettings
5454
public bool IsDryRun { get; init; }
5555

5656
[CommandOption("-v|--verify")]
57-
[Description("Verify that all analized code does not require modifications to excise server scopes.")]
57+
[Description("Verify that all analyzed code does not require modifications to excise server scopes.")]
5858
public bool Verify { get; init; }
5959

60+
[CommandOption("--strict")]
61+
[Description("Ensure that all files can be analyzed without syntactic or lexicographical errors.")]
62+
public bool StrictMode { get; init; }
63+
6064
[CommandArgument(0, "[INPUT]")]
6165
[Description("The input folder to excise.")]
6266
public string InputPath { get; init; } = string.Empty;
@@ -87,6 +91,7 @@ public override int Execute([NotNull] CommandContext context, [NotNull] Settings
8791
parameters.ShouldOutputUntouchedFiles = settings.ShouldOutputUntouchedFiles;
8892
parameters.IsDryRun = settings.IsDryRun || settings.ShouldOutputUntouchedFiles || settings.Verify;
8993
parameters.Verify = settings.Verify;
94+
parameters.StrictMode = settings.StrictMode;
9095
parameters.UseFunctionStats = settings.UseFunctionStats;
9196
parameters.DontSkip = settings.DontSkip;
9297
if (settings.RequiredExcisionRatio.HasValue)

ServerCodeExciser/ServerCodeExcisionProcessor.cs

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public class ServerCodeExcisionParameters
1717
public bool ShouldOutputUntouchedFiles { get; set; } = false;
1818
public bool IsDryRun { get; set; } = false;
1919
public bool Verify { get; set; } = false;
20+
public bool StrictMode { get; set; } = false;
2021
public bool UseFunctionStats { get; set; } = false;
2122
public bool DontSkip { get; set; } = false;
2223
public float RequiredExcisionRatio { get; set; } = -1.0f;
@@ -109,8 +110,7 @@ public EExciserReturnValues ExciseServerCode(string filePattern, IServerCodeExci
109110
{
110111
System.Diagnostics.Debug.Assert(stats.TotalNrCharacters > 0, "Something is terribly wrong. We have excised characters, but no total characters..?");
111112
var excisionRatio = (float)stats.CharactersExcised / (float)stats.TotalNrCharacters * 100.0f;
112-
Console.WriteLine("Excised {0:0.00}% of server only code in file ({1}/{2}): {3}",
113-
excisionRatio, fileIdx + 1, allFiles.Length, fileName);
113+
Console.WriteLine("Excised {0:0.00}% of server only code in file ({1}/{2}): {3}", excisionRatio, fileIdx + 1, allFiles.Length, fileName);
114114
}
115115
else
116116
{
@@ -120,9 +120,10 @@ public EExciserReturnValues ExciseServerCode(string filePattern, IServerCodeExci
120120
globalStats.CharactersExcised += stats.CharactersExcised;
121121
globalStats.TotalNrCharacters += stats.TotalNrCharacters;
122122
}
123-
catch (Exception e)
123+
catch (Exception)
124124
{
125125
Console.WriteLine("Failed to parse ({0}/{1}): {2}", fileIdx + 1, allFiles.Length, fileName);
126+
throw;
126127
}
127128
}
128129
}
@@ -183,10 +184,17 @@ private ExcisionStats ProcessCodeFile(string fileName, string inputPath, EExcisi
183184
// Setup parsing and output.
184185
List<KeyValuePair<int, string>> serverCodeInjections = new List<KeyValuePair<int, string>>();
185186
var inputStream = new AntlrInputStream(script);
186-
var lexer = excisionLanguage.CreateLexer(inputStream);
187+
var lexer = excisionLanguage.CreateLexer<UnrealAngelscriptLexer>(inputStream);
187188
lexer.AddErrorListener(new ExcisionLexerErrorListener());
188189
var commonTokenStream = new CommonTokenStream(lexer);
189-
var parser = excisionLanguage.CreateParser(commonTokenStream);
190+
var parser = excisionLanguage.CreateParser<UnrealAngelscriptParser>(commonTokenStream);
191+
parser.AddErrorListener(new ExcisionParserErrorListener());
192+
193+
if (_parameters.StrictMode)
194+
{
195+
parser.ErrorHandler = new BailErrorStrategy();
196+
}
197+
190198
var answerText = new StringBuilder();
191199
answerText.Append(script);
192200

@@ -195,7 +203,7 @@ private ExcisionStats ProcessCodeFile(string fileName, string inputPath, EExcisi
195203
{
196204
// We want to excise this entire file.
197205
serverCodeInjections.Add(new KeyValuePair<int, string>(0, excisionLanguage.ServerScopeStartString + "\r\n"));
198-
serverCodeInjections.Add(new KeyValuePair<int, string>(script.Length, excisionLanguage.ServerScopeEndString));
206+
serverCodeInjections.Add(new KeyValuePair<int, string>(script.Length, excisionLanguage.ServerScopeEndString + "\r\n"));
199207
stats.CharactersExcised += script.Length;
200208
}
201209
else if (excisionMode == EExcisionMode.AllFunctions)
@@ -221,7 +229,8 @@ private ExcisionStats ProcessCodeFile(string fileName, string inputPath, EExcisi
221229
// Gather all the injections we want to make
222230
if (visitor != null)
223231
{
224-
visitor.VisitContext(parser.GetParseTree());
232+
visitor.VisitContext(parser.script());
233+
225234
if (_parameters.UseFunctionStats)
226235
{
227236
stats.TotalNrCharacters = visitor.TotalNumberOfFunctionCharactersVisited;
@@ -232,17 +241,17 @@ private ExcisionStats ProcessCodeFile(string fileName, string inputPath, EExcisi
232241
{
233242
if (currentScope.StartIndex == -1
234243
|| currentScope.StopIndex == -1
235-
|| InjectedMacroAlreadyExistsAtLocation(answerText, currentScope.StartIndex, true, excisionLanguage.ServerScopeStartString)
236-
|| InjectedMacroAlreadyExistsAtLocation(answerText, currentScope.StartIndex, false, excisionLanguage.ServerScopeStartString)
237-
|| InjectedMacroAlreadyExistsAtLocation(answerText, currentScope.StopIndex, false, excisionLanguage.ServerScopeEndString))
244+
|| InjectedMacroAlreadyExistsAtLocation(answerText, currentScope.StartIndex, true, true, excisionLanguage.ServerScopeStartString)
245+
|| InjectedMacroAlreadyExistsAtLocation(answerText, currentScope.StartIndex, false, false, excisionLanguage.ServerScopeStartString)
246+
|| InjectedMacroAlreadyExistsAtLocation(answerText, currentScope.StopIndex, false, false, excisionLanguage.ServerScopeEndString))
238247
{
239248
continue;
240249
}
241250

242251
// If there are already injected macros where we want to go, we should skip injecting.
243252
System.Diagnostics.Debug.Assert(currentScope.StopIndex > currentScope.StartIndex, "There must be some invalid pattern here! Stop is before start!");
244-
serverCodeInjections.Add(new KeyValuePair<int, string>(currentScope.StartIndex, excisionLanguage.ServerScopeStartString));
245-
serverCodeInjections.Add(new KeyValuePair<int, string>(currentScope.StopIndex, currentScope.Opt_ElseContent + excisionLanguage.ServerScopeEndString));
253+
serverCodeInjections.Add(new KeyValuePair<int, string>(currentScope.StartIndex, "\r\n" + excisionLanguage.ServerScopeStartString));
254+
serverCodeInjections.Add(new KeyValuePair<int, string>(currentScope.StopIndex, currentScope.Opt_ElseContent + excisionLanguage.ServerScopeEndString + "\r\n"));
246255
stats.CharactersExcised += currentScope.StopIndex - currentScope.StartIndex;
247256
}
248257

@@ -257,10 +266,10 @@ private ExcisionStats ProcessCodeFile(string fileName, string inputPath, EExcisi
257266
dummyRefDataBlockString.Append("\r\n\t" + dummyVarDef);
258267
}
259268

260-
dummyRefDataBlockString.Append("\r\n" + excisionLanguage.ServerScopeEndString + "\r\n");
269+
dummyRefDataBlockString.Append("\r\n" + excisionLanguage.ServerScopeEndString + "\r\n\r\n");
261270

262271
// If there is already a block of dummy reference variables we skip adding new ones, there is no guarantee we are adding the right code.
263-
if (InjectedMacroAlreadyExistsAtLocation(answerText, dummyRefDataPair.Key, false, dummyVarScope + "\r\n"))
272+
if (InjectedMacroAlreadyExistsAtLocation(answerText, dummyRefDataPair.Key, false, true, dummyVarScope + "\r\n"))
264273
{
265274
continue;
266275
}
@@ -314,19 +323,47 @@ private ExcisionStats ProcessCodeFile(string fileName, string inputPath, EExcisi
314323
return stats;
315324
}
316325

317-
private bool InjectedMacroAlreadyExistsAtLocation(StringBuilder script, int index, bool lookAhead, string macro)
326+
private static bool IsWhitespace(char c)
318327
{
319-
int startIndex = lookAhead ? index : (index - macro.Length);
320-
int endIndex = lookAhead ? (index + macro.Length) : index;
328+
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
329+
}
321330

322-
if (startIndex < 0 || startIndex >= script.Length
323-
|| endIndex < 0 || endIndex >= script.Length)
331+
private bool InjectedMacroAlreadyExistsAtLocation(StringBuilder script, int index, bool lookAhead, bool ignoreWhitespace, string macro)
332+
{
333+
if (lookAhead)
324334
{
325-
return false;
335+
if (ignoreWhitespace)
336+
{
337+
while (index < script.Length && IsWhitespace(script[index]))
338+
{
339+
index++;
340+
}
341+
}
342+
343+
if (script.Length - index < macro.Length)
344+
{
345+
return false;
346+
}
347+
348+
return script.ToString(index, macro.Length).Equals(macro);
326349
}
350+
else
351+
{
352+
if (ignoreWhitespace)
353+
{
354+
while (index > 0 && IsWhitespace(script[index]))
355+
{
356+
index--;
357+
}
358+
}
359+
360+
if (index - macro.Length < 0)
361+
{
362+
return false;
363+
}
327364

328-
string scriptSection = script.ToString(startIndex, macro.Length);
329-
return scriptSection == macro;
365+
return script.ToString(index - macro.Length, macro.Length).Equals(macro);
366+
}
330367
}
331368
}
332369
}

ServerCodeExciserTest/ExcisionIntegrationTests.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public static int Main(string[] args)
3434
ref numTestCases);
3535

3636
Console.WriteLine("----------------------------");
37-
Console.WriteLine($"{numTestCases - numTestFailures} test(s) passed.");
37+
Console.WriteLine($"{numTestCases} test(s) executed.");
3838
Console.WriteLine($"{numTestFailures} test(s) failed.");
3939
}
4040
catch (Exception e)
@@ -54,7 +54,8 @@ private static EExciserReturnValues RunExciserIntegrationTests(string fileExtens
5454
Directory.Delete(outputPath, true);
5555
}
5656

57-
string searchPattern = "*" + fileExtension.TrimStart('.');
57+
string searchPattern = "*." + fileExtension.TrimStart('.');
58+
Console.WriteLine($"Running integration tests for {searchPattern} files...");
5859

5960
EExciserReturnValues returnCode;
6061
try
@@ -65,17 +66,17 @@ private static EExciserReturnValues RunExciserIntegrationTests(string fileExtens
6566
ShouldOutputUntouchedFiles = true,
6667
FullExcisionRegexString = @"FullExcise1/.*",
6768
ExciseAllFunctionsRegexString = @"AllFunctionExcise1/.*|||AllFunctionExcise2/.*",
69+
StrictMode = true,
6870
};
6971
excisionParams.InputPaths.Add(inputPath);
7072

7173
var angelscriptServerCodeExciser = new ServerCodeExcisionProcessor(excisionParams);
7274
returnCode = angelscriptServerCodeExciser.ExciseServerCode(searchPattern, new UnrealAngelscriptServerCodeExcisionLanguage());
73-
Console.WriteLine($"ExciseServerCode for {fileExtension} files returned: {returnCode}");
75+
Console.WriteLine($"ExciseServerCode for {searchPattern} files returned: {returnCode}");
7476
}
75-
catch (Exception e)
77+
catch (Exception)
7678
{
77-
AnsiConsole.WriteException(e);
78-
return EExciserReturnValues.InternalExcisionError;
79+
throw;
7980
}
8081

8182
foreach (var answerFilePath in Directory.EnumerateFiles(outputPath, searchPattern, SearchOption.AllDirectories))

ServerCodeExciserTest/Problems/Common/DeclarationInFunctionRootScopeWithReturnValTest.common

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class UDeclarationInFunctionRootScopeWithReturnValTest
5050
{
5151
ensure(System::IsServer());
5252

53-
float64 ThisMustBeGuarded = 0.0f;
53+
float64 ThisMustBeGuarded = 0.0;
5454
ThisMustBeGuarded--;
5555

5656
return ThisMustBeGuarded;

ServerCodeExciserTest/Problems/Common/FullExcise1/FullExcise1Test.common.solution

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
#ifdef WITH_SERVER
32
class UFullExcise1Test
43
{

ServerCodeExcisionCommon/IServerCodeExcisionLanguage.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,23 @@ public interface IServerCodeExcisionLanguage
99
List<string> ServerOnlySymbols { get; }
1010

1111
string ServerPrecompilerSymbol { get; }
12+
1213
string ServerScopeStartString { get; }
14+
1315
string ServerScopeEndString { get; }
1416

15-
Antlr4.Runtime.Lexer CreateLexer(Antlr4.Runtime.AntlrInputStream inputStream);
16-
IServerCodeParser CreateParser(Antlr4.Runtime.CommonTokenStream tokenStream);
17-
17+
T CreateLexer<T>(Antlr4.Runtime.AntlrInputStream inputStream)
18+
where T : Antlr4.Runtime.Lexer;
19+
20+
T CreateParser<T>(Antlr4.Runtime.CommonTokenStream tokenStream)
21+
where T : Antlr4.Runtime.Parser;
22+
1823
IServerCodeVisitor CreateSimpleVisitor(string code);
24+
1925
IServerCodeVisitor CreateFunctionVisitor(string code);
26+
2027
IServerCodeVisitor CreateSymbolVisitor(string code);
21-
28+
2229
bool AnyServerOnlySymbolsInScript(string script);
2330
}
2431
}

ServerCodeExcisionCommon/IServerCodeParser.cs

Lines changed: 0 additions & 9 deletions
This file was deleted.

ServerCodeExcisionCommon/ServerCodeExcisionUtils.cs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@ public enum EExciserReturnValues
8989

9090
public class ExcisionException : Exception
9191
{
92-
public ExcisionException(string excisionError, Exception innerException) : base(excisionError, innerException) {}
92+
public ExcisionException(string excisionError, Exception innerException)
93+
: base(excisionError, innerException)
94+
{
95+
}
9396
}
9497

9598
public class ExcisionParserErrorListener : Antlr4.Runtime.IAntlrErrorListener<Antlr4.Runtime.IToken>
@@ -143,24 +146,6 @@ public static int FindScriptIndexForCodePoint(string script, int line, int colum
143146
return (linesTraversed == line) ? (cursor + column) : -1;
144147
}
145148

146-
public static int ShrinkServerScope(string script, int start, int end)
147-
{
148-
bool skip = true;
149-
while (skip)
150-
{
151-
skip = false;
152-
153-
int search = script.IndexOfAny(NewLineChars, start) + 2;
154-
if ((search < end) && SkippableScopeChars.Contains<char>(script.ElementAt(search)))
155-
{
156-
skip = true;
157-
++start;
158-
}
159-
}
160-
161-
return start;
162-
}
163-
164149
public static Type FindFirstDirectChildOfType<Type>(Antlr4.Runtime.Tree.IParseTree currentContext)
165150
where Type : class
166151
{

UnrealAngelscriptParser/Grammar/UnrealAngelscriptParser.g4

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,8 @@ memberSpecification:
496496

497497
memberdeclaration:
498498
propertyDefinition
499+
| classSpecifier
500+
| enumSpecifier
499501
| functionDefinition
500502
| aliasDeclaration
501503
| emptyDeclaration

UnrealAngelscriptServerCodeExcision/UnrealAngelsciptServerCodeParser.cs

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)