Commit 86ac22d4 authored by Jesse McGrew's avatar Jesse McGrew

Various .NET Core cleanup recommended by analyzers and Sharper.

parent 62ba0b9cc06c
......@@ -56,25 +56,18 @@ namespace ZilfAnalyzers.Test.Helpers
[JetBrains.Annotations.NotNull]
static string ToSafeString(this char c)
{
switch (c)
return c switch
{
case '\r':
return @"\r";
case '\n':
return @"\n";
case '\t':
return @"\t";
case '\a':
return @"\a";
case '\v':
return @"\v";
case '\f':
return @"\f";
default:
return char.IsControl(c) || char.IsWhiteSpace(c)
? $"\\u{(int)c:X};"
: c.ToString(CultureInfo.InvariantCulture);
}
'\r' => @"\r",
'\n' => @"\n",
'\t' => @"\t",
'\a' => @"\a",
'\v' => @"\v",
'\f' => @"\f",
_ => char.IsControl(c) || char.IsWhiteSpace(c)
? $"\\u{(int)c:X};"
: c.ToString(CultureInfo.InvariantCulture),
};
}
}
......
......@@ -40,9 +40,17 @@ namespace ZilfAnalyzers.Test.Helpers
/// <param name="newSource">A class in the form of a string after the CodeFix was applied to it</param>
/// <param name="codeFixIndex">Index determining which codefix to apply if there are multiple</param>
/// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("AsyncUsage", "AsyncFixer01:Unnecessary async/await usage", Justification = "VS template code")]
protected async Task VerifyCSharpFixAsync(string oldSource, string newSource, int? codeFixIndex = null, bool allowNewCompilerDiagnostics = false)
{
await VerifyFixAsync(LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), GetCSharpCodeFixProvider(), oldSource, newSource, codeFixIndex, allowNewCompilerDiagnostics);
await VerifyFixAsync(LanguageNames.CSharp,
GetCSharpDiagnosticAnalyzer(),
GetCSharpCodeFixProvider(),
oldSource,
newSource,
codeFixIndex,
allowNewCompilerDiagnostics)
.ConfigureAwait(false);
}
/// <summary>
......@@ -52,9 +60,17 @@ namespace ZilfAnalyzers.Test.Helpers
/// <param name="newSource">A class in the form of a string after the CodeFix was applied to it</param>
/// <param name="codeFixIndex">Index determining which codefix to apply if there are multiple</param>
/// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("AsyncUsage", "AsyncFixer01:Unnecessary async/await usage", Justification = "VS template code")]
protected async Task VerifyBasicFixAsync(string oldSource, string newSource, int? codeFixIndex = null, bool allowNewCompilerDiagnostics = false)
{
await VerifyFixAsync(LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), GetBasicCodeFixProvider(), oldSource, newSource, codeFixIndex, allowNewCompilerDiagnostics);
await VerifyFixAsync(LanguageNames.VisualBasic,
GetBasicDiagnosticAnalyzer(),
GetBasicCodeFixProvider(),
oldSource,
newSource,
codeFixIndex,
allowNewCompilerDiagnostics)
.ConfigureAwait(false);
}
/// <summary>
......@@ -85,21 +101,21 @@ namespace ZilfAnalyzers.Test.Helpers
for (int i = 0; i < attempts; ++i)
{
var actions = new List<CodeAction>();
var context = new CodeFixContext(document, analyzerDiagnostics[0], (a, d) => actions.Add(a), CancellationToken.None);
var context = new CodeFixContext(document, analyzerDiagnostics[0], (a, _) => actions.Add(a), CancellationToken.None);
await codeFixProvider.RegisterCodeFixesAsync(context).ConfigureAwait(false);
if (!actions.Any())
if (actions.Count == 0)
{
break;
}
if (codeFixIndex != null)
{
document = ApplyFix(document, actions.ElementAt((int)codeFixIndex));
document = ApplyFix(document, actions[(int)codeFixIndex]);
break;
}
document = ApplyFix(document, actions.ElementAt(0));
document = ApplyFix(document, actions[0]);
analyzerDiagnostics = await GetSortedDiagnosticsFromDocumentsAsync(analyzer, new[] { document }).ConfigureAwait(false);
analyzerDiagnostics = analyzerDiagnostics.Where(d => fixableIds.Contains(d.Id)).ToArray();
......@@ -109,17 +125,17 @@ namespace ZilfAnalyzers.Test.Helpers
if (!allowNewCompilerDiagnostics && newCompilerDiagnostics.Any())
{
// Format and get the compiler diagnostics again so that the locations make sense in the output
document = document.WithSyntaxRoot(Formatter.Format(document.GetSyntaxRootAsync().Result, Formatter.Annotation, document.Project.Solution.Workspace));
document = document.WithSyntaxRoot(Formatter.Format(await document.GetSyntaxRootAsync().ConfigureAwait(false), Formatter.Annotation, document.Project.Solution.Workspace));
newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(document));
Assert.Fail(
"Fix introduced new compiler diagnostics:\r\n{0}\r\n\r\nNew document:\r\n{1}\r\n",
string.Join("\r\n", newCompilerDiagnostics.Select(d => d.ToString())),
document.GetSyntaxRootAsync().Result.ToFullString());
(await document.GetSyntaxRootAsync().ConfigureAwait(false)).ToFullString());
}
//check if there are analyzer diagnostics left after the code fix
if (!analyzerDiagnostics.Any())
if (analyzerDiagnostics.Length == 0)
{
break;
}
......
......@@ -46,7 +46,7 @@ namespace Dezapf
}
}
class DataChunk : Chunk
sealed class DataChunk : Chunk
{
public byte[] Bytes { get; }
......@@ -137,7 +137,7 @@ namespace Dezapf
}
}
class GlobalsChunk : Chunk
sealed class GlobalsChunk : Chunk
{
public ushort[] Values { get; }
......@@ -150,7 +150,7 @@ namespace Dezapf
public static GlobalsChunk FromStream(Stream stream, int offset, int length)
{
stream.Seek(offset, SeekOrigin.Begin);
BinaryReader rdr = new BinaryReader(stream);
var rdr = new BinaryReader(stream);
int count = length / 2;
ushort[] values = new ushort[count];
for (int i = 0; i < count; i++)
......
......@@ -165,7 +165,7 @@ namespace Dezapf
{
System.Diagnostics.Debug.Assert(zversion >= 3);
StringBuilder sb = new StringBuilder(encodedText.Length * 3);
var sb = new StringBuilder(encodedText.Length * 3);
int mode = 0; // 0/1/2 = alphabets, 3 = ASCII state 1, 4 = ASCII state 2
int pendingAscii = 0;
......
......@@ -132,18 +132,13 @@ namespace Dezapf
class HeaderChunk : Chunk
{
readonly Header hdr;
public HeaderChunk(int pc, int length, Header hdr)
: base(pc, length)
{
this.hdr = hdr;
Header = hdr;
}
public Header Header
{
get { return hdr; }
}
public Header Header { get; }
public override void WriteTo(TextWriter writer, Context ctx)
{
......
......@@ -41,7 +41,7 @@ namespace Dezapf
ShortPositive = 0xc0,
}
class Instruction : Chunk
sealed class Instruction : Chunk
{
ushort op;
ushort[] operands;
......@@ -204,7 +204,7 @@ namespace Dezapf
ushort[] encodedText = null;
if ((attr.Flags & ZOpFlags.String) != 0)
{
List<ushort> list = new List<ushort>();
var list = new List<ushort>();
ushort w;
do
{
......
......@@ -39,7 +39,7 @@ namespace Dezapf
protected string FormatFlags1(Context ctx, byte flags1)
{
StringBuilder sb = new StringBuilder();
var sb = new StringBuilder();
if (ctx.ZVersion <= 3)
{
if ((flags1 & 1) != 0)
......
......@@ -28,178 +28,177 @@ namespace Dezapf
{
public static void Main(string[] args)
{
using (Stream stream = new FileStream(args[0], FileMode.Open, FileAccess.Read))
{
var fileLength = (int)stream.Length;
var rdr = new BinaryReader(stream);
using Stream stream = new FileStream(args[0], FileMode.Open, FileAccess.Read);
var fileLength = (int)stream.Length;
var rdr = new BinaryReader(stream);
var ctx = new Context();
var ranges = new RangeList<Chunk>();
var hdr = new Header(rdr);
var ctx = new Context();
var ranges = new RangeList<Chunk>();
var hdr = new Header(rdr);
ctx.Header = hdr;
ctx.OutputStyle = new ZapRoundTripStyle();
ctx.Header = hdr;
ctx.OutputStyle = new ZapRoundTripStyle();
ranges.AddRange(0, 64, new HeaderChunk(0, 64, hdr));
ranges.AddRange(0, 64, new HeaderChunk(0, 64, hdr));
// find instructions
var todo = new Stack<int>();
var pendingFuncs = new Queue<int>();
var pastFuncs = new HashSet<int>();
var maxGlobal = 0;
todo.Push(hdr.Start);
// find instructions
var todo = new Stack<int>();
var pendingFuncs = new Queue<int>();
var pastFuncs = new HashSet<int>();
var maxGlobal = 0;
todo.Push(hdr.Start);
while (todo.Count > 0)
{
var pc = todo.Pop();
while (todo.Count > 0)
if (ranges.TryGetValue(pc, out _) == false)
{
var pc = todo.Pop();
stream.Seek(pc, SeekOrigin.Begin);
var inst = Instruction.Decode(ctx, rdr, pc);
if (ranges.TryGetValue(pc, out _) == false)
if (inst != null)
{
stream.Seek(pc, SeekOrigin.Begin);
var inst = Instruction.Decode(ctx, rdr, pc);
ranges.AddRange(pc, inst.Length, inst);
if (inst != null)
{
ranges.AddRange(pc, inst.Length, inst);
for (var i = 0; i < inst.OperandTypes.Length; i++)
if (inst.OperandTypes[i] == OperandType.Variable && inst.Operands[i] >= 16)
maxGlobal = Math.Max(maxGlobal, inst.Operands[i]);
for (var i = 0; i < inst.OperandTypes.Length; i++)
if (inst.OperandTypes[i] == OperandType.Variable && inst.Operands[i] >= 16)
maxGlobal = Math.Max(maxGlobal, inst.Operands[i]);
if (inst.BranchType != BranchType.None &&
inst.BranchOffset != 0 && inst.BranchOffset != 1)
{
todo.Push(pc + inst.Length + inst.BranchOffset - 2);
}
if (inst.BranchType != BranchType.None &&
inst.BranchOffset != 0 && inst.BranchOffset != 1)
{
todo.Push(pc + inst.Length + inst.BranchOffset - 2);
}
var attr = ctx.GetOpcodeInfo(inst.Op);
var attr = ctx.GetOpcodeInfo(inst.Op);
if ((attr.Flags & ZOpFlags.Terminates) == 0)
todo.Push(pc + inst.Length);
if ((attr.Flags & ZOpFlags.Terminates) == 0)
todo.Push(pc + inst.Length);
if ((attr.Flags & ZOpFlags.Call) != 0)
{
switch (inst.OperandTypes[0])
{
case OperandType.Word:
case OperandType.Byte:
pendingFuncs.Enqueue(ctx.UnpackAddress(inst.Operands[0], hdr.RoutineOffset));
break;
}
}
else if ((attr.Flags & ZOpFlags.Label) != 0)
if ((attr.Flags & ZOpFlags.Call) != 0)
{
switch (inst.OperandTypes[0])
{
switch (inst.OperandTypes[0])
{
case OperandType.Word:
case OperandType.Byte:
todo.Push(pc + inst.Length + (short)inst.Operands[0] - 2);
break;
}
case OperandType.Word:
case OperandType.Byte:
pendingFuncs.Enqueue(ctx.UnpackAddress(inst.Operands[0], hdr.RoutineOffset));
break;
}
}
else
else if ((attr.Flags & ZOpFlags.Label) != 0)
{
//XXX
Console.WriteLine("* Invalid instruction at PC={0:x5}", pc);
switch (inst.OperandTypes[0])
{
case OperandType.Word:
case OperandType.Byte:
todo.Push(pc + inst.Length + (short)inst.Operands[0] - 2);
break;
}
}
}
else
{
//XXX
Console.WriteLine("* Invalid instruction at PC={0:x5}", pc);
}
}
while (todo.Count == 0 && pendingFuncs.Count > 0)
while (todo.Count == 0 && pendingFuncs.Count > 0)
{
var funcAddr = pendingFuncs.Dequeue();
if (!pastFuncs.Contains(funcAddr))
{
var funcAddr = pendingFuncs.Dequeue();
if (!pastFuncs.Contains(funcAddr))
{
pastFuncs.Add(funcAddr);
stream.Seek(funcAddr, SeekOrigin.Begin);
funcAddr++;
pastFuncs.Add(funcAddr);
stream.Seek(funcAddr, SeekOrigin.Begin);
funcAddr++;
// skip function header
int locals = rdr.ReadByte();
if (ctx.ZVersion < 5)
funcAddr += 2 * locals;
// skip function header
int locals = rdr.ReadByte();
if (ctx.ZVersion < 5)
funcAddr += 2 * locals;
todo.Push(funcAddr);
}
todo.Push(funcAddr);
}
}
}
// combine instructions into routines
foreach (var address in pastFuncs)
ComposeFunc(ctx, stream, rdr, ranges, address);
// mark global variables
maxGlobal -= 15;
if (maxGlobal > 0)
{
var globalsChunk = GlobalsChunk.FromStream(stream, hdr.Globals, maxGlobal * 2);
ranges.AddRange(hdr.Globals, maxGlobal * 2, globalsChunk);
}
// combine instructions into routines
foreach (var address in pastFuncs)
ComposeFunc(ctx, stream, rdr, ranges, address);
// mark memory borders
if (!ranges.Contains(hdr.EndLod))
ranges.AddRange(hdr.EndLod, 1, DataChunk.FromStream(stream, hdr.EndLod, 1));
// mark global variables
maxGlobal -= 15;
if (maxGlobal > 0)
{
var globalsChunk = GlobalsChunk.FromStream(stream, hdr.Globals, maxGlobal * 2);
ranges.AddRange(hdr.Globals, maxGlobal * 2, globalsChunk);
}
if (!ranges.Contains(hdr.Impure))
ranges.AddRange(hdr.Impure, 1, DataChunk.FromStream(stream, hdr.Impure, 1));
// mark memory borders
if (!ranges.Contains(hdr.EndLod))
ranges.AddRange(hdr.EndLod, 1, DataChunk.FromStream(stream, hdr.EndLod, 1));
// fill in gaps with data chunks
var gapChunks = new Queue<DataChunk>();
foreach (var gap in ranges.FindGaps(0, fileLength))
gapChunks.Enqueue(DataChunk.FromStream(stream, gap.Start, gap.Length));
while (gapChunks.Count > 0)
{
var chunk = gapChunks.Dequeue();
if (!ranges.Contains(hdr.Impure))
ranges.AddRange(hdr.Impure, 1, DataChunk.FromStream(stream, hdr.Impure, 1));
// skip padding chunks filled with zeroes
if (ranges.TryGetValue(chunk.PC + chunk.Length, out var nextChunk) &&
chunk.Length < nextChunk.GetAlignment(ctx) &&
chunk.Bytes.All(b => b == 0))
{
continue;
}
// fill in gaps with data chunks
var gapChunks = new Queue<DataChunk>();
foreach (var gap in ranges.FindGaps(0, fileLength))
gapChunks.Enqueue(DataChunk.FromStream(stream, gap.Start, gap.Length));
while (gapChunks.Count > 0)
{
var chunk = gapChunks.Dequeue();
ranges.AddRange(chunk.PC, chunk.Length, chunk);
// skip padding chunks filled with zeroes
if (ranges.TryGetValue(chunk.PC + chunk.Length, out var nextChunk) &&
chunk.Length < nextChunk.GetAlignment(ctx) &&
chunk.Bytes.All(b => b == 0))
{
continue;
}
// output
Chunk lastChunk = null;
foreach (var r in ranges)
{
if (lastChunk != null && r.Value.WantNewParagraph(lastChunk))
Console.WriteLine();
ranges.AddRange(chunk.PC, chunk.Length, chunk);
}
if (r.Start > 0)
{
if (r.Start == hdr.AlphabetTable)
Console.WriteLine("ALPHABET::");
if (r.Start == hdr.EndLod)
Console.WriteLine("ENDLOD::");
if (r.Start == hdr.ExtensionTable)
Console.WriteLine("HDREXT::");
if (r.Start == hdr.Words)
Console.WriteLine("WORDS::");
if (r.Start == hdr.Globals)
Console.WriteLine("GLOBAL::");
if (r.Start == hdr.Impure)
Console.WriteLine("IMPURE::");
if (r.Start == hdr.Objects)
Console.WriteLine("OBJECT::");
if (r.Start == hdr.RoutineOffset * 8)
Console.WriteLine("ROUTINES::");
if (r.Start == hdr.Start)
Console.WriteLine("START::");
if (r.Start == hdr.StringOffset * 8)
Console.WriteLine("STRINGS::");
if (r.Start == hdr.TCharsTable)
Console.WriteLine("TCHARS::");
if (r.Start == hdr.Vocab)
Console.WriteLine("VOCAB::");
}
// output
Chunk lastChunk = null;
foreach (var r in ranges)
{
if (lastChunk != null && r.Value.WantNewParagraph(lastChunk))
Console.WriteLine();
r.Value.WriteTo(Console.Out, ctx);
lastChunk = r.Value;
if (r.Start > 0)
{
if (r.Start == hdr.AlphabetTable)
Console.WriteLine("ALPHABET::");
if (r.Start == hdr.EndLod)
Console.WriteLine("ENDLOD::");
if (r.Start == hdr.ExtensionTable)
Console.WriteLine("HDREXT::");
if (r.Start == hdr.Words)
Console.WriteLine("WORDS::");
if (r.Start == hdr.Globals)
Console.WriteLine("GLOBAL::");
if (r.Start == hdr.Impure)
Console.WriteLine("IMPURE::");
if (r.Start == hdr.Objects)
Console.WriteLine("OBJECT::");
if (r.Start == hdr.RoutineOffset * 8)
Console.WriteLine("ROUTINES::");
if (r.Start == hdr.Start)
Console.WriteLine("START::");
if (r.Start == hdr.StringOffset * 8)
Console.WriteLine("STRINGS::");
if (r.Start == hdr.TCharsTable)
Console.WriteLine("TCHARS::");
if (r.Start == hdr.Vocab)
Console.WriteLine("VOCAB::");
}
r.Value.WriteTo(Console.Out, ctx);
lastChunk = r.Value;
}
//Console.ReadKey();
......
......@@ -67,12 +67,7 @@ namespace Dezapf
}
}
readonly List<Range> list;
public RangeList()
{
list = new List<Range>();
}
readonly List<Range> list = new List<Range>();
public void Add(Range range)
{
......@@ -106,7 +101,7 @@ namespace Dezapf
{
if (list.Count > 0)
{
Range r = new Range(position, 0, default(T));
var r = new Range(position, 0, default);
int idx = list.BinarySearch(r);
if (idx < 0)
......@@ -133,7 +128,7 @@ namespace Dezapf
}
}
value = default(T);
value = default;
return false;
}
......
......@@ -325,7 +325,6 @@ General switches:
-c #### set creator version
-ab also optimize abbreviations and print ZAPF code
-dx use XML debug format");
}
/// <exception cref="FatalError">An <see cref="IOException"/> occurred while reading the input file(s).</exception>
......@@ -1314,7 +1313,7 @@ General switches:
break;
case DebugArrayDirective darr:
if (ctx.GlobalSymbols.TryGetValue("GLOBAL", out var sym1) == false)
if (!ctx.GlobalSymbols.TryGetValue("GLOBAL", out var sym1))
{
Errors.Serious(ctx, node, "define GLOBAL before using .DEBUG-ARRAY");
return;
......@@ -1450,7 +1449,7 @@ General switches:
AlignRoutine(ctx);