dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.67k stars 4.58k forks source link

List of Redundant conditional #94522

Open skyoxZ opened 8 months ago

skyoxZ commented 8 months ago

94262 reports a redundant conditional. I wrote a simple program scanning the repo to see if I could find more. It scans all .cpp/.cs files except those under /src/tests/JIT/(I thought they are not a problem). It should report all blocks matching:

xxx
{
    ...
}
else
{
    // exact same block
}

https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/coreclr/jit/emitriscv64.cpp#L4176-#L4183 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Data.OleDb/src/DbConnectionOptions.cs#L500-#L505 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L642-#L661 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L691-#L710 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L740-#L759 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L798-#L817 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L840-#L859 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L880-#L899 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L922-#L941 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Private.Xml/tests/XmlReaderLib/ReadOuterXml.cs#L377-#L384 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Private.Xml/tests/XmlReaderLib/ReadOuterXml.cs#L404-#L411 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Private.Xml/tests/XmlReaderLib/CXmlReaderReadEtc.cs#L232-#L239 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Private.Xml/tests/XmlReaderLib/CXmlReaderReadEtc.cs#L385-#L392 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CodeGenerator.cs#L498-#L505

My program if anyone interested:

source code ```csharp string repoDir = "/Users/zhangningshen/zns-dotnet-runtime"; string commitHash = File.ReadAllText(Path.Combine(repoDir, ".git/refs/heads/main")).Trim(); foreach (string filePath in Directory.EnumerateFiles(repoDir, "*.cpp", SearchOption.AllDirectories)) { DealFile(filePath); } foreach (string filePath in Directory.EnumerateFiles(repoDir, "*.cs", SearchOption.AllDirectories)) { DealFile(filePath); } void DealFile(string filePath) { string[] lines = File.ReadAllLines(filePath); int start = 1; while (true) { int lineElse = FindLineElse(lines, start); if (lineElse == -1) return; Tuple? result = Deal(lines, lineElse); if (result != null) { WriteResult(filePath, result); } start = lineElse + 1; } } void WriteResult(string filePath, Tuple block) { string relativePath = filePath[repoDir.Length..].Replace('\\', '/'); if (relativePath.StartsWith("/src/tests/JIT/")) return; Console.WriteLine($"https://github.com/dotnet/runtime/blob/{commitHash}{relativePath}#L{block.Item1 + 1}-#L{block.Item2 + 1}"); } Tuple? Deal(string[] lines, int lineElse) { int aEnd = lineElse - 1; int bStart = lineElse + 1; if (lines[aEnd].Trim() != "}" || lines[bStart].Trim() != "{") return null; int bEnd = FindLineEnd(lines, bStart + 1, lines[aEnd]); if (bEnd == -1) return null; int aStart = aEnd - bEnd + bStart; if (aStart < 0) return null; if (lines[aStart] != lines[bStart]) return null; if (BlockEquals(lines, aStart, aEnd, bStart)) return Tuple.Create(aStart - 1, bEnd); return null; } int FindLineElse(string[] lines, int start) { for (int i = start; i < lines.Length; i++) { if (lines[i].Trim() == "else") return i; } return -1; } int FindLineEnd(string[] lines, int start, string endString) { for (int i = start; i < lines.Length; i++) { if (lines[i] == endString) return i; } return -1; } bool BlockEquals(string[] lines, int aStart, int aEnd, int bStart) { int b = bStart; for (int a = aStart; a < aEnd; a++, b++) { if (lines[a] != lines[b]) return false; } return true; } ```
ShreyasJejurkar commented 8 months ago

OMG, this is strange and yet surprising to me!

This can be a Roslyn analyzer at least for the C# side.

ghost commented 8 months ago

Tagging subscribers to this area: @dotnet/area-system-runtime See info in area-owners.md if you want to be subscribed.

Issue Details
#94262 reports a redundant conditional. I wrote a simple program scanning the repo to see if I could find more. It scans all .cpp/.cs files except those under `/src/tests/JIT/`(I thought they are not a problem). It should report all blocks matching: ```csharp xxx { ... } else { // exact same block } ``` https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/coreclr/jit/emitriscv64.cpp#L4176-#L4183 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Data.OleDb/src/DbConnectionOptions.cs#L500-#L505 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L642-#L661 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L691-#L710 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L740-#L759 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L798-#L817 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L840-#L859 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L880-#L899 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs#L922-#L941 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Private.Xml/tests/XmlReaderLib/ReadOuterXml.cs#L377-#L384 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Private.Xml/tests/XmlReaderLib/ReadOuterXml.cs#L404-#L411 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Private.Xml/tests/XmlReaderLib/CXmlReaderReadEtc.cs#L232-#L239 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Private.Xml/tests/XmlReaderLib/CXmlReaderReadEtc.cs#L385-#L392 https://github.com/dotnet/runtime/blob/f3e7d46955784e5273ba1e90233ae244319f2a9f/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CodeGenerator.cs#L498-#L505 My program if anyone interested:
source code ```csharp string repoDir = "/Users/zhangningshen/zns-dotnet-runtime"; string commitHash = File.ReadAllText(Path.Combine(repoDir, ".git/refs/heads/main")).Trim(); foreach (string filePath in Directory.EnumerateFiles(repoDir, "*.cpp", SearchOption.AllDirectories)) { DealFile(filePath); } foreach (string filePath in Directory.EnumerateFiles(repoDir, "*.cs", SearchOption.AllDirectories)) { DealFile(filePath); } void DealFile(string filePath) { string[] lines = File.ReadAllLines(filePath); int start = 1; while (true) { int lineElse = FindLineElse(lines, start); if (lineElse == -1) return; Tuple? result = Deal(lines, lineElse); if (result != null) { WriteResult(filePath, result); } start = lineElse + 1; } } void WriteResult(string filePath, Tuple block) { string relativePath = filePath[repoDir.Length..].Replace('\\', '/'); if (relativePath.StartsWith("/src/tests/JIT/")) return; Console.WriteLine($"https://github.com/dotnet/runtime/blob/{commitHash}{relativePath}#L{block.Item1 + 1}-#L{block.Item2 + 1}"); } Tuple? Deal(string[] lines, int lineElse) { int aEnd = lineElse - 1; int bStart = lineElse + 1; if (lines[aEnd].Trim() != "}" || lines[bStart].Trim() != "{") return null; int bEnd = FindLineEnd(lines, bStart + 1, lines[aEnd]); if (bEnd == -1) return null; int aStart = aEnd - bEnd + bStart; if (aStart < 0) return null; if (lines[aStart] != lines[bStart]) return null; if (BlockEquals(lines, aStart, aEnd, bStart)) return Tuple.Create(aStart - 1, bEnd); return null; } int FindLineElse(string[] lines, int start) { for (int i = start; i < lines.Length; i++) { if (lines[i].Trim() == "else") return i; } return -1; } int FindLineEnd(string[] lines, int start, string endString) { for (int i = start; i < lines.Length; i++) { if (lines[i] == endString) return i; } return -1; } bool BlockEquals(string[] lines, int aStart, int aEnd, int bStart) { int b = bStart; for (int a = aStart; a < aEnd; a++, b++) { if (lines[a] != lines[b]) return false; } return true; } ```
Author: skyoxZ
Assignees: -
Labels: `area-System.Runtime`, `untriaged`, `needs-area-label`
Milestone: -