fix scheme name resolution, and schema load on WSL (#5327)

This PR fixes the scheme resolution bug outlined in #5326

The approach is as follows:

* In [SchemeManager.cs], find the first scheme parser that actually
  successfully parses the scheme, as opposed to the existing code, which
  finds the first scheme parser which _says it can parse the scheme_, as
  that logic spuriously returns `true` currently. 
* In [XmlSchemeParser.cs] and [JsonParser.cs], ensure that the contents
  of the file are read and the contents passed to XmlDocument.LoadXXX,
  as this fails with an UriException on WSL otherwise.
* Remove `CanParse` as it is superfluous. The check for a valid scheme
  parser should not just check an extension but also if the file exists
  - this is best done by the `ParseScheme` function as it already
  returns null on failure.
* Add `FileExtension` to the interface because we need it lifted now.

Closes #5326
This commit is contained in:
John Azariah 2020-07-01 13:15:09 -07:00 committed by GitHub
parent 44e80d40b6
commit 436fac6afa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 487 additions and 492 deletions

View File

@ -91,9 +91,8 @@ namespace ColorTool
public static ColorScheme GetScheme(string schemeName, bool reportErrors = false)
{
return GetParsers()
.Where(parser => parser.CanParse(schemeName))
.Select(parser => parser.ParseScheme(schemeName, reportErrors))
.FirstOrDefault();
.FirstOrDefault(x => x != null);
}
public static IEnumerable<ISchemeParser> GetParsers()

View File

@ -8,7 +8,7 @@ namespace ColorTool.SchemeParsers
interface ISchemeParser
{
string Name { get; }
bool CanParse(string schemeName);
string FileExtension { get; }
ColorScheme ParseScheme(string schemeName, bool reportErrors = false);
}
}

View File

@ -18,7 +18,7 @@ namespace ColorTool.SchemeParsers
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
protected override string FileExtension { get; } = ".ini";
public override string FileExtension { get; } = ".ini";
// These are in Windows Color table order - BRG, not RGB.
internal static readonly IReadOnlyList<string> ColorNames = new[]
@ -43,9 +43,6 @@ namespace ColorTool.SchemeParsers
public override string Name { get; } = "INI File Parser";
public override bool CanParse(string schemeName) =>
string.Equals(Path.GetExtension(schemeName), FileExtension, StringComparison.OrdinalIgnoreCase);
public override ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
{
bool success = true;

View File

@ -15,7 +15,7 @@ namespace ColorTool.SchemeParsers
{
class JsonParser : SchemeParserBase
{
protected override string FileExtension { get; } = ".json";
public override string FileExtension { get; } = ".json";
private static readonly IReadOnlyList<string> ConcfgColorNames = new[]
{
"black", // Dark Black
@ -38,9 +38,6 @@ namespace ColorTool.SchemeParsers
public override string Name { get; } = "concfg Parser";
public override bool CanParse(string schemeName) =>
string.Equals(Path.GetExtension(schemeName), FileExtension, StringComparison.OrdinalIgnoreCase);
public override ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
{
XmlDocument xmlDoc = LoadJsonFile(schemeName);
@ -117,25 +114,29 @@ namespace ColorTool.SchemeParsers
return RGB(col.R, col.G, col.B);
}
private XmlDocument LoadJsonFile(string schemeName)
{
XmlDocument xmlDoc = new XmlDocument();
foreach (string path in SchemeManager.GetSearchPaths(schemeName, FileExtension)
.Where(File.Exists))
private XmlDocument LoadJsonFile(string schemeName) =>
SchemeManager
.GetSearchPaths(schemeName, FileExtension)
.Select(path =>
{
try
{
var data = File.ReadAllBytes(path);
var reader = JsonReaderWriterFactory.CreateJsonReader(data, System.Xml.XmlDictionaryReaderQuotas.Max);
var reader = JsonReaderWriterFactory.CreateJsonReader(data, XmlDictionaryReaderQuotas.Max);
var xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
return xmlDoc;
}
catch (XmlException /*e*/) { /* failed to parse */ }
catch (IOException /*e*/) { /* failed to find */ }
catch (UnauthorizedAccessException /*e*/) { /* unauthorized */ }
catch (XmlException) { }
catch (IOException) { }
catch (UnauthorizedAccessException) { }
catch (Exception e)
{
Console.WriteLine($"Unexpected Exception: {e}.\nBailing...");
throw;
}
return null;
}
})
.FirstOrDefault(x => x != null);
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -12,17 +13,13 @@ namespace ColorTool.SchemeParsers
public abstract string Name { get; }
public abstract bool CanParse(string schemeName);
public abstract ColorScheme ParseScheme(string schemeName, bool reportErrors = false);
// Common elements and helpers
protected abstract string FileExtension { get; }
public abstract string FileExtension { get; }
protected string ExtractSchemeName(string schemeFileName)
{
return schemeFileName.Substring(0, schemeFileName.Length - FileExtension.Length);
}
protected string ExtractSchemeName(string schemeFileName) =>
Path.ChangeExtension(schemeFileName, null);
}
}

View File

@ -4,7 +4,6 @@
//
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@ -42,13 +41,10 @@ namespace ColorTool.SchemeParsers
private const string GreenKey = "Green Component";
private const string BlueKey = "Blue Component";
protected override string FileExtension { get; } = ".itermcolors";
public override string FileExtension { get; } = ".itermcolors";
public override string Name { get; } = "iTerm Parser";
public override bool CanParse(string schemeName) =>
string.Equals(Path.GetExtension(schemeName), FileExtension, StringComparison.OrdinalIgnoreCase);
public override ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
{
XmlDocument xmlDoc = LoadXmlScheme(schemeName); // Create an XML document object
@ -126,23 +122,28 @@ namespace ColorTool.SchemeParsers
return true;
}
private XmlDocument LoadXmlScheme(string schemeName)
{
XmlDocument xmlDoc = new XmlDocument(); // Create an XML document object
foreach (string path in SchemeManager.GetSearchPaths(schemeName, FileExtension)
.Where(File.Exists))
private XmlDocument LoadXmlScheme(string schemeName) =>
SchemeManager
.GetSearchPaths(schemeName, FileExtension)
.Select(path =>
{
try
{
xmlDoc.Load(path);
var text = File.ReadAllText(path);
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(text);
return xmlDoc;
}
catch (XmlException /*e*/) { /* failed to parse */ }
catch (IOException /*e*/) { /* failed to find */ }
catch (UnauthorizedAccessException /*e*/) { /* unauthorized */ }
catch (XmlException) { }
catch (IOException) { }
catch (UnauthorizedAccessException) { }
catch (Exception e)
{
Console.WriteLine($"Unexpected Exception: {e}.\nBailing...");
throw;
}
return null;
}
})
.FirstOrDefault(x => x != null);
}
}