in SharpGen/Transform/RelationParser.cs [27:104]
public static IReadOnlyList<MarshallableRelation> ParseRelation(string relation, Logger logger)
{
if (string.IsNullOrWhiteSpace(relation))
return null;
var wrappedRelations = WrapRelation(
relation,
out var structSizeReplacementCount,
out var constReplacementCount
);
try
{
var tree = SyntaxFactory.ParseExpression(wrappedRelations, options: SharpParseOptions);
if (tree is not ImplicitArrayCreationExpressionSyntax arrayCreationTree)
{
logger.Error(LoggingCodes.InvalidRelation, "Relation [{0}] parse failed: internal expression wrapping error. Ignoring.", relation);
return null;
}
var relationsList = arrayCreationTree.Initializer.Expressions;
var result = relationsList.Select(ParseSingleRelation).ToArray();
if (result.All(x => x.Relation != null))
{
// Success, do diagnostics and return result.
if (structSizeReplacementCount != result.Count(x => x.Relation is StructSizeRelation && x.Identifier == StructSizeReplacement))
logger.Warning(
LoggingCodes.InvalidRelation,
"Relation [{0}] replaced extra \"{1}\" substrings.", relation, StructSizeLegacy
);
if (constReplacementCount != result.Count(x => x.Relation is ConstantValueRelation && x.Identifier == ConstReplacement))
logger.Warning(
LoggingCodes.InvalidRelation,
"Relation [{0}] replaced extra \"{1}\" substrings.", relation, ConstLegacy
);
return result.Select(x => x.Relation).ToArray();
}
// At least one relation failed to parse.
foreach (var (failedResult, i) in result.Select((x, i) => (Result: x, i)).Where(x => x.Result.Relation == null))
{
// If source of the failure is too short, it wouldn't look good or helpful.
// Use full span of that failed relation instead.
var sourceSpan = failedResult.IssueSource.Length > 3
? failedResult.IssueSource
: relationsList[i].Span;
logger.Error(
LoggingCodes.InvalidRelation,
"Sub-relation [{0}] parse failed: {1}.",
wrappedRelations.Substring(sourceSpan.Start, sourceSpan.Length),
failedResult.IssueDescription
);
}
logger.Error(LoggingCodes.InvalidRelation, "Relation [{0}] parse failed due to the previous errors. Ignoring.", relation);
return null;
}
catch (Exception exception)
{
logger.Error(
LoggingCodes.InvalidRelation,
"Relation [{0}] parse failed: {1} — {2}. Ignoring.",
exception,
relation,
exception.GetType().Name,
exception.Message
);
return null;
}
}