c # — получить имя функции из базы текстовых файлов в строке кода

Я получил источник C ++ под названием «MyCpp.cpp», он находится в: C: \ MyCpp.cpp

...
5 string CplusplusWarningFunction()
6 {
7   int a = 69;
8   int b = a + 1;
9   a = b;
10  b = 69;
11  return "42 is the answer";
12 }
...

Теперь я хочу написать функцию C #, как это

void CodeAnalyzer()
{
string path = @"C:\MyCpp.cpp";
int line = 11;
IEnumerable<string> loc = File.ReadLines(path);

string code = loc.ElementAt(line-1);//Yes, it is 'return "42 is the answer";', good job!
string functionFullName = "???";//This suppose to be the string 'CplusplusWarningFunction()', but How to do it???
MessageBox.Show(string.Format("The code {0} at line {1} is in function {2}",code,line,functionFullName));
}

Как я могу получить имя функции, чтобы заменить строку «???» в коде C # выше?

Я знаю, что это можно сделать, потому что MS ‘FxCop может сделать это, вроде (FxCop анализирует скомпилированный объектный код, а не исходный код). Хорошо, если скомпилированный объектный код можно сделать, почему бы не исходный исходный код.

И Visual Studio может сделать это, как показано на рисунке ниже, я надеюсь, что есть способ получить доступ к Visual Studio API:
введите описание изображения здесь

Спасибо за чтение.

1

Решение

Учитывая, что есть только одна функция, для каждой строки вы можете попробовать

//do this in a foreach loop that will iterate through every line
string functionName;
if (line.Split(' ').Where(x => x.Contains("()") && !x.Contains(".")).Count() > 0)
{
functionName = line.Split(' ').Where(x => x.Contains("()") && !x.Contains(".")).First();
}

Теперь это будет работать на вашем примере кода, но это также очень рудиментарный, и я уверен, что во многих случаях это не сработает. Это не может быть плохой отправной точкой, хотя.

1

Другие решения

Я придумаю такой код, и он пока неплох.

class CppFunction
{
public string FunctionName { get; set; }
public int StartLine { get; set; }
public int EndLines { get; set; }
}

List<CppFunction> AnalyzeCpp(string path)
{
List<CppFunction> lstCppFunc = new List<CppFunction>();

IEnumerable<string> loc = File.ReadLines(path, encode);

string[] locNoCom = RemoveComment(loc);
RemoveIfdefineDebug(locNoCom);
int level = 0;

CppFunction crtFunc = null;
int lineCount = 0;
StringBuilder builder = new StringBuilder();
bool startName = false;
string builderToString;
string lastLine = "";
foreach (string line in locNoCom)
{
lineCount++;
if (string.IsNullOrWhiteSpace(line))
{
lastLine = line;
continue;
}

if (level <= 0)
{
if (line.Contains('('))
{
crtFunc = new CppFunction();
if (line.Trim().IndexOf('(') == 0)
builder.Append(lastLine);
builder.AppendLine(line);
crtFunc.StartLine = lineCount;
startName = true;
}
if (startName)
{
builderToString = builder.ToString();
if (line != builderToString.Replace("\r\n",string.Empty))
builder.AppendLine(line);
if (line.Contains(')'))
{
startName = false;
if (crtFunc != null)
crtFunc.FunctionName = builder.ToString();
builder.Clear();
}
}
}

if(line.Contains('{'))
{
foreach(char c in line)
{
if (c == '{')
level++;
}
}
if(line.Contains('}'))
{
foreach (char c in line)
{
if (c == '}')
level--;
}
if (crtFunc != null && level <= 0)
{
crtFunc.EndLines = lineCount;
lstCppFunc.Add(crtFunc);
crtFunc = null;
level = 0;
}
}
lastLine = line;
}

return lstCppFunc;
}

Теперь у нас есть список Function и ее начальная строка, конечная строка, когда мы получили строку кода, мы можем проверить, находится ли она между какой функцией, и BAM — мы получили строку функции.

Редактировать:
Нам также нужно удалить комментарий, чтобы увеличить праведность

string[] RemoveComment(IEnumerable<string> loc)
{
string[] line = loc.ToArray();
bool startComment = false;
int startComPos=0;
int endComPos=-1;
int count = line.Length;
string comment;

bool mistakeComment;

int multiCommentStart, multiCommentEnd;

for(int i=0;i<count;i++)
{
if (string.IsNullOrWhiteSpace(line[i]))
continue;
if (line[i].Contains("//"))
{
mistakeComment = false;
if(line[i].Contains("*//*"))//Case mistake /**//**/ with //
{
if ((line[i].IndexOf("//") - line[i].IndexOf("*//*")) == 1)
{
mistakeComment = true;
}
}

if(!mistakeComment)
{
comment = line[i].Substring(line[i].IndexOf("//"));
line[i] = line[i].Replace(comment, string.Empty);
}
}
if(line[i].Contains("/*"))
{
startComment = true;
startComPos = line[i].IndexOf("/*");
endComPos = -1;
}
else
{
startComPos = 0;
}

if (startComment)
{
if(!string.IsNullOrEmpty(line[i]))
{
if (line[i].Contains("*/"))
{
startComment = false;
endComPos = line[i].IndexOf("*/", startComPos);
}
else
endComPos = -1;
if (endComPos == -1)
{
comment = line[i].Substring(startComPos);
line[i] = line[i].Replace(comment, string.Empty);
}
else
{
comment = line[i].Substring(startComPos, endComPos - startComPos + 2);
line[i] = line[i].Replace(comment, string.Empty);
}
}
}

if (line[i].Contains("/*"))
while((multiCommentStart = line[i].IndexOf("/*")) >= 0 &&
(multiCommentEnd = line[i].IndexOf("*/")) >= 0 &&
multiCommentEnd > multiCommentStart)
{
comment = line[i].Substring(multiCommentStart, multiCommentEnd - multiCommentStart + 2);
line[i] = line[i].Replace(comment, string.Empty);
}
}
return line;
}

О, и мы также должны удалить код отладки также

void RemoveIfdefineDebug(string[] linesCode)
{
bool startRemove = false;
for(int i=0;i<linesCode.Length;i++)
{
if(startRemove)
{
if (linesCode[i].Contains("#endif"))
{
startRemove = false;
}
else
linesCode[i] = string.Empty;
}
if (linesCode[i].Contains("#ifdef "))
{
startRemove = true;
}
}
}

И, наконец, основная функция

string GetCodeAndFunctionName(string path, int line)
{
List<CppFunction> lstCppFunc = AnalyzeCpp(path);
foreach(CppFunction func in lstCppFunc)
{
if(func.EndLines >= line && func.StartLine <= line)
{
return func.FunctionName;
}
}
return "x";
}
1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector