Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Change Log
All notable changes to this project since version 1.0.14 will be documented in this file.

## [3.2.0] - 22.02.2025
**Description:**
Heuristics improvements in various areas visible in input files: 58 & 59.

Among others: improved methods handling and keywords like: "required", "virtual", "unsafe", "partial", "delegate"

## [3.1.0] - 09.02.2025
**Description:**

Expand Down
2 changes: 1 addition & 1 deletion src/Core/Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<PackageProjectUrl>https://github.com/Swiftly1/CsharpToColouredHTML</PackageProjectUrl>
<RepositoryUrl>https://github.com/Swiftly1/CsharpToColouredHTML</RepositoryUrl>
<PackageId>CsharpToColouredHTML.Core</PackageId>
<Version>3.1.0</Version>
<Version>3.2.0</Version>
<Description>C# to HTML converter with syntax highlighting</Description>
<PackageTags>c#;html;converter;syntax;highlighting</PackageTags>
<RepositoryType>git</RepositoryType>
Expand Down
52 changes: 21 additions & 31 deletions src/Core/HeuristicsGeneration/HeuristicsHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,17 @@ private bool IsClassOrStructAlreadyFound(string text)
return false;
}

private string ResolveName(string text)
private string ResolveName(string text, bool hint_mustBeClassLike = false)
{
if (!text.Any(x => char.IsLetter(x)))
return NodeColors.Default;

if (hint_mustBeClassLike)
{
if (!IsValidClassOrStructName(text))
return NodeColors.Identifier;
}

if (IsPopularStruct(text))
return NodeColors.Struct;

Expand All @@ -233,11 +242,14 @@ private string ResolveName(string text)
if (_FoundStructs.Contains(text))
return NodeColors.Struct;

if (_FoundPropertiesOrFields.Contains(text))
return NodeColors.PropertyName;
if (!hint_mustBeClassLike)
{
if (_FoundPropertiesOrFields.Contains(text))
return NodeColors.PropertyName;

if (_FoundLocalNames.Contains(text))
return NodeColors.LocalName;
if (_FoundLocalNames.Contains(text))
return NodeColors.LocalName;
}

bool startsWithI = NameLikeInterface(text);

Expand All @@ -247,8 +259,8 @@ private string ResolveName(string text)
if (_Hints.BuiltInTypes.Contains(text))
return NodeColors.Keyword;

if (!IsValidClassOrStructName(text))
return NodeColors.Identifier;
if (text.EndsWith("Struct"))
return NodeColors.Struct;

return NodeColors.Class;
}
Expand All @@ -258,29 +270,6 @@ private static bool NameLikeInterface(string text)
return text.StartsWith("I") && text.Length > 1 && char.IsUpper(text[1]);
}

private string ResolveClassOrStructName(string text)
{
if (!IsValidClassOrStructName(text))
return NodeColors.Identifier;

if (IsPopularStruct(text))
return NodeColors.Struct;

if (IsPopularClass(text))
return NodeColors.Class;

if (_FoundClasses.Contains(text))
return NodeColors.Class;

if (_FoundStructs.Contains(text))
return NodeColors.Struct;

if (text.EndsWith("Struct"))
return NodeColors.Struct;

return NodeColors.Class;
}

private bool IsValidClassOrStructName(string text)
{
if (IdentifierFirstCharCaseSeemsLikeVariable(text))
Expand Down Expand Up @@ -325,7 +314,8 @@ private bool IsPopularStruct(string text)

private static readonly List<string> CommonKeywordsBeforeTypeName = new List<string>
{
"public", "private", "internal", "sealed", "protected", "readonly", "static", "override", "event"
"public", "private", "internal", "sealed", "protected", "readonly", "static", "override", "event", "required",
"virtual", "unsafe", "partial", "delegate"
};

private static readonly List<string> Operators = new List<string>
Expand Down
57 changes: 47 additions & 10 deletions src/Core/HeuristicsGeneration/HeuristicsLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,6 @@ private bool IsClassOrStruct()
if (!IsValidClassOrStructName(CurrentText))
return false;

if (IdentifierFirstCharCaseSeemsLikeVariable(CurrentText))
return false;

if (TryPeekBehind(out var peekedBehindNode) && TryPeekBehind(out var peekedBehindNode2, 2) &&
peekedBehindNode.Text == "." &&
peekedBehindNode2.Text == ">")
Expand Down Expand Up @@ -289,6 +286,14 @@ private bool IsClassOrStruct()
}
}

// catch (Exception ex)
if (TryPeekBehind(out peekedBehindNode) && peekedBehindNode.Text == "(" &&
TryPeekBehind(out peekedBehindNode2, 2) && peekedBehindNode2.Text == "catch")
{
found = true;
goto Exit;
}

// EqualityComparer<T1>
// EqualityComparer<T1, T2, T3>
if (CheckAndMarkGenericParametersChain())
Expand Down Expand Up @@ -326,6 +331,10 @@ private bool IsProperty()
ClassificationTypeNames.ConstantName,
ClassificationTypeNames.FieldName,
ClassificationTypeNames.ParameterName,
ClassificationTypeNames.StructName,
ClassificationTypeNames.ClassName,
ClassificationTypeNames.RecordClassName,
ClassificationTypeNames.RecordStructName,
};

if (TryPeekBehind(out var peekedOperator) && peekedOperator.Text == "." &&
Expand All @@ -351,13 +360,29 @@ private bool IsProperty()
}
}

// var id = home.Areas?.FirstOrDefault()?.Id;
if (TryPeekBehind(out peekedOperator) && peekedOperator.Text == "." &&
TryPeekBehind(out peekedOperator2, 2) && peekedOperator2.Text == "?" &&
TryPeekBehind(out var peekedParenthesis, 3) && peekedParenthesis.Text == ")" &&
TryPeekAhead(out peekedAhead) && peekedAhead.Text != "(")
{
MarkNodeAs(NodeColors.PropertyName);
return true;
}

if (TryPeekBehind(out peekedOperator) && peekedOperator.Text == "." &&
TryPeekBehind(out var peekedIndexer, 2) && peekedIndexer.Text == "]")
{
MarkNodeAs(NodeColors.PropertyName);
return true;
}

if (TryPeekAhead(out peekedIndexer) && peekedIndexer.Text == "[")
{
MarkNodeAs(NodeColors.PropertyName);
return true;
}

if (TryPeekBehind(out peekedOperator) && peekedOperator.Text.EqualsAnyOf("{", ",") &&
TryPeekAhead(out var peekedNext) && peekedNext.Text.Contains("="))
{
Expand All @@ -366,7 +391,7 @@ private bool IsProperty()
}

if (TryPeekBehind(out peekedOperator) && peekedOperator.Text == "." &&
TryPeekBehind(out var peekedParenthesis, 2) && peekedParenthesis.Text == ")")
TryPeekBehind(out peekedParenthesis, 2) && peekedParenthesis.Text == ")")
{
MarkNodeAs(NodeColors.PropertyName);
return true;
Expand Down Expand Up @@ -412,7 +437,7 @@ private bool IsProperty()
// return pos.Row < 0 || pos.Row >= Rows || pos.Col < 0 || pos.Col >= Cols;
if (TryPeekBehind(out peekedOperator) && Operators.Contains(peekedOperator.Text))
{
if (TryPeekAhead(out var nodeAhead1) && nodeAhead1.Text == ";")
if (TryPeekAhead(out var nodeAhead1) && nodeAhead1.Text.EqualsAnyOf(";", "}"))
{
MarkNodeLocalNameOrProperty(CurrentNode);
return true;
Expand All @@ -426,7 +451,8 @@ private bool IsProperty()
return true;
}

if (TryPeekAhead(out var nodeAhead) && nodeAhead.Text == "," &&
// public static IEnumerable<(TSource Source, TOut Out)>
if (TryPeekAhead(out var nodeAhead) && nodeAhead.Text.EqualsAnyOf(",", ")") &&
CurrentNode.ClassificationType == ClassificationTypeNames.Identifier)
{
MarkNodeLocalNameOrProperty(CurrentNode);
Expand Down Expand Up @@ -481,13 +507,19 @@ private bool IsMethod()
{
if (TryPeekAhead(out var peekedNode) && peekedNode.Text == "(")
{
if (!CanMoveBehind())
{
MarkNodeAs(NodeColors.Method);
return true;
}

if (TryPeekBehind(out var peekBehind))
{
if (peekBehind.Text == "new")
{
return false;
}
else if (peekBehind.Text.EqualsAnyOf(".", "return", "await", "="))
else if (peekBehind.Text.EqualsAnyOf(".", "return", "await", "=", "=>"))
{
var newIsUsed = CheckIfThereIsNewBeforeMethodCall();
if (newIsUsed)
Expand Down Expand Up @@ -532,7 +564,12 @@ private bool IsMethod()
}
else if (peekBehind.ClassificationType == ClassificationTypeNames.Identifier)
{
MarkNodeAs(peekBehind, ResolveClassOrStructName(peekBehind.Text));
MarkNodeAs(peekBehind, ResolveName(peekBehind.Text));
MarkNodeAs(NodeColors.Method);
return true;
}
else if (peekBehind.ClassificationType.EqualsAnyOf(ClassificationTypeNames.Comment, ClassificationTypeNames.Punctuation))
{
MarkNodeAs(NodeColors.Method);
return true;
}
Expand Down Expand Up @@ -678,7 +715,7 @@ private bool IsKeyword()
if (validIdentifiers1.Contains(peekedAhead1.ClassificationType) &&
peekedAhead2.Text.EqualsAnyOf("(", "{", "["))
{
var colour = ResolveClassOrStructName(peekedAhead1.Text);
var colour = ResolveName(peekedAhead1.Text, true);
MarkNodeAs(peekedAhead1, colour);
MoveNext();
}
Expand Down Expand Up @@ -707,7 +744,7 @@ private bool IsKeyword()
if (TryPeekAhead(out var nodeAhead) && nodeAhead.ClassificationType == ClassificationTypeNames.Identifier)
{
MoveNext();
var colour = ResolveClassOrStructName(nodeAhead.Text);
var colour = ResolveName(nodeAhead.Text);
MarkNodeAs(nodeAhead, colour);
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/Core/HeuristicsGeneration/StateMachines/TypeNameWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ void MarkTupleElements(List<Node> chainElements, bool markIt)
}
else if (node.Id == identifiers[^2].Id)
{
var color = ResolveClassOrStructName(node.Text);
var color = ResolveName(node.Text);
MarkNodeAs(node, color);
}
else
Expand All @@ -296,7 +296,7 @@ void MarkTupleElements(List<Node> chainElements, bool markIt)
}
else if (!valueTupleTypeWithName && node.Id == identifiers[^1].Id)
{
var color = ResolveClassOrStructName(node.Text);
var color = ResolveName(node.Text);
MarkNodeAs(node, color);
}
else
Expand Down Expand Up @@ -349,6 +349,10 @@ private bool CheckAndMarkGenericParametersChain()
{
MarkNodeAs(entry, ClassificationTypeNames.Punctuation);
}
else if (entry.ClassificationType == ClassificationTypeNames.Operator)
{
MarkNodeAs(entry, ClassificationTypeNames.Operator);
}
else
{
var colour = ResolveName(entry.Text);
Expand Down
2 changes: 2 additions & 0 deletions src/Tests/FilesTestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ public IEnumerator<object[]> GetEnumerator()
yield return new object[] { "0055.txt" };
yield return new object[] { "0056.txt" };
yield return new object[] { "0057.txt" };
yield return new object[] { "0058.txt" };
yield return new object[] { "0059.txt" };
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
Expand Down
46 changes: 46 additions & 0 deletions src/Tests/InputCsharp/0058.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
TryParse("123", int.TryParse, out var intResult);

public static int GetLengthAtCoord(int X, int Y)
{
var pair = (X, Y);
return Mapper[pair];
}

public void Test()
{
// Perform Run
RunTest();

if (3 > 4)
RunTest2();
}

public void CalculatePublic() => CalculateInternal(5);

public void Test4(bool useAbc)
{
var strategy = = useAbc ? Strategies.A : Strategies.B;
}

private readonly float[] Entries = new float[]
{
1, 2
};

protected override void OnPageBegin()
{
User user = new User()
{
Name = "test",
Email = Entries
};
}

public static IEnumerable<(TSource Source, TOut Out)> WhereOut<TSource, TOut>(this IEnumerable<TSource> source, TryGet<TSource, TOut> tryGet)
{
}

public void Test7()
{
var id = home.Areas?.FirstOrDefault()?.HomeId;
}
29 changes: 29 additions & 0 deletions src/Tests/InputCsharp/0059.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
```csharp
try
{

}
catch (Exception ex)
{
}
```

unsafe partial class LongBoiContainer
{
protected internal required override sealed unsafe partial delegate* LongBoi { get => field; set; }
}

unsafe partial class LongBoiContainer2
{
protected unsafe LongBoi2 { get => field; set; }
}

unsafe partial class LongBoiContainer3
{
protected partial int LongBoi3 { get => field; set; }
}

unsafe partial class LongBoiContainer4
{
protected delegate double LongBoi3 { get => field; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,6 @@

<span class="namespace">Test123</span><span class="operator">.</span><span class="class">Company</span> <span class="localName">oCompany</span>

<span class="class">NFANode</span> <span class="method">GetOrCreate</span><span class="punctuation">(</span><span class="class">ImmutableArray</span><span class="operator">&lt;</span><span class="class">NFANode</span><span class="identifier">&gt;</span> <span class="localName">set</span><span class="punctuation">)</span>
<span class="class">NFANode</span> <span class="method">GetOrCreate</span><span class="punctuation">(</span><span class="class">ImmutableArray</span><span class="operator">&lt;</span><span class="class">NFANode</span><span class="operator">&gt;</span> <span class="localName">set</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
<span class="punctuation">}</span></pre>

Large diffs are not rendered by default.

Loading
Loading