У меня есть программа с большим количеством математических вычислений. Он был преобразован из VB6, где деление двух целых чисел дает двойное число. Мне нужно найти все места, где он делит два целых числа, чтобы я мог привести целые числа к удвоению, чтобы он выполнял деление с плавающей запятой вместо целочисленного деления.
Лучшее, что я смог придумать, это декомпилировать код с помощью ILDASM и найти 5B.*div в полученном файле .il: https://en.wikipedia.org/wiki/List_of_CIL_instructions
Но есть только одна инструкция для всех типов деления, так что проверить типы аргументов в стековой машине довольно сложно.
Есть ли более надежный способ найти все экземпляры целочисленного деления?
Расширение Roslyn должно иметь доступ к семантике кода. Вы пробовали это? Какие исследования вы уже провели? Был ли grep текста IL лучшим или единственным, что вы пробовали до сих пор? В чем конкретно вы ищете помощи? Stack Overflow не является подходящим форумом для получения готовых решений с нуля.
@PeterDuniho Я бы посчитал «Создайте расширение для анализа кода Roslyn, вот 2 или 3 строки соответствующего кода, чтобы указать вам правильное направление» очень хороший ответ на этот вопрос, и я бы отметил это как принятый ответ.
Комментарий Питера Дунихо указал мне правильное направление, чтобы использовать анализатор кода Roslyn. Этот код — отличное место для начала создания анализатора:
https://johkoerner.com/csharp/creating-a-stand-alone-code-analyzer/
Код для этого очень короткий, начните с проекта Extensibility -> Stand-Alone Code Analysis Tool.
void DoAnalysis(string solutionPath)
{
var ws = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkplace.Create();
var soln = ws.OpenSolutionAsync(solutionPath).Result;
foreach (var proj in soln.Projects)
{
var compile = proj.GetCompilationAsync().Result;
foreach (var tree in compile.SyntaxTrees)
{
var symantic = compile.GetSemanticModel(tree);
foreach (var divide in tree.GetRoot().DescendantNodesAndSel()
.Where(i => i.IsKind(SyntaxKind.DivideExpression))
.OfType<BinaryExpressionSyntax>())
{
if (semantic.GetTypeInfo(divide.Left).ConvertedType.Name == "Int32"
&& semantic.GetTypeInfo(divide.Right).ConvertedType.Name == "Int32")
{
Consel.WriteLine("File " + tree.FilePath + " at " + divide.Span.Start);
}
}
}
}
}
Это довольно убедительный пример того, почему важно правильное покрытие тестами.