将标记和琐事映射到行号 [英] Map tokens and trivia to line numbers

查看:54
本文介绍了将标记和琐事映射到行号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Roslyn 将标记和琐事映射到行号.

I'm trying to map tokens and trivia to line numbers using Roslyn.

这是我在下方@Kevin Pilch-Bisson 的帮助下的最新尝试.

Here's my latest attempt with help from @Kevin Pilch-Bisson below.

public class CSharpSlocAnalyser : ISlocAnalyser
{
    public long GetSlocFor(IEnumerable<FileInfo> files, SlocOptions options)
    {
        var tree = CSharpSyntaxTree.ParseText(
@"using /* Blah */
    System;
// Blah
public class MyClass
{
    public void MyMethod()
    {
        var blah = ""abc"";
    }
}");

        var root = tree.GetRoot();
        var walker = new CustomWalker();
        walker.Visit(root);
        var lineMap = walker.LineMap;

        return 1;
    }

    public class CustomWalker : CSharpSyntaxWalker
    {
        public Dictionary<int, List<object>> LineMap { get; }

        public CustomWalker() : base(SyntaxWalkerDepth.StructuredTrivia)
        {
            LineMap = new Dictionary<int, List<object>>();
        }

        public override void VisitToken(SyntaxToken token)
        {
            var parent = token.Parent;
            while (parent.GetText().Length < token.Span.Start)
            {
                parent = parent.Parent;
            }

            var text = parent.GetText();
            var line = text.Lines.GetLineFromPosition(token.Span.Start).LineNumber;

            if (!LineMap.ContainsKey(line))
            {
                LineMap.Add(line, new List<object>());
            }

            LineMap[line].Add(token);

            base.VisitToken(token);
        }

        public override void VisitTrivia(SyntaxTrivia trivia)
        {
            var parent = trivia.Token.Parent;
            while (parent.GetText().Length < trivia.Span.Start)
            {
                parent = parent.Parent;
            }

            var text = parent.GetText();
            var line = text.Lines.GetLineFromPosition(trivia.Span.Start).LineNumber;

            if (!LineMap.ContainsKey(line))
            {
                LineMap.Add(line, new List<object>());
            }

            LineMap[line].Add(trivia);

            base.VisitTrivia(trivia);
        }
    }
}

然而,这会产生以下地图:

However this produces the following map:

Line 0
    UsingKeyword - 'using'
    WhitespaceTrivia - ' '
    MultiLineCommentTrivia - '/* Blah */'
    EndOfLineTrivia - '
'
Line 1
    IdentifierToken - 'System'
    WhitespaceTrivia - '    '
    SemicolonToken - ';'
    EndOfLineTrivia - '
'
Line 2
    SingleLineCommentTrivia - '// Blah'
Line 3
    PublicKeyword - 'public'
    EndOfLineTrivia - '
'
    WhitespaceTrivia - ' '
    ClassKeyword - 'class'
    WhitespaceTrivia - ' '
    IdentifierToken - 'MyClass'
    EndOfLineTrivia - '
'
    WhitespaceTrivia - '    '
Line 4
    OpenBraceToken - '{'
    EndOfLineTrivia - '
'
    PublicKeyword - 'public'
Line 5
    WhitespaceTrivia - ' '
    VoidKeyword - 'void'
    WhitespaceTrivia - ' '
    IdentifierToken - 'MyMethod'
    OpenParenToken - '('
    CloseParenToken - ')'
    EndOfLineTrivia - '
'
    WhitespaceTrivia - '    '
Line 6
    OpenBraceToken - '{'
    EndOfLineTrivia - '
'
    WhitespaceTrivia - '        '
Line 7
    IdentifierToken - 'var'
    WhitespaceTrivia - ' '
    IdentifierToken - 'blah'
    WhitespaceTrivia - ' '
    EqualsToken - '='
    WhitespaceTrivia - ' '
    StringLiteralToken - '"abc"'
    SemicolonToken - ';'
    EndOfLineTrivia - '
'
Line 8
    CloseBraceToken - '}'
    WhitespaceTrivia - '    '
    EndOfLineTrivia - '
'
Line 9
    CloseBraceToken - '}'
    EndOfFileToken - ''

一切看起来都很好,直到第 2 行,它不包含行尾琐事,第 3 行包含 2 个行尾琐事,一切似乎都从那里脱离了轨道.

Everything looks good until Line 2, which does not contain and end of line trivia, Line 3 contains 2 end of line trivia's, and everything seems to go off the rails from there.

我做错了什么?我只想将标记和琐事映射到它们的原始源代码行号.

What am I doing wrong? I just want to map tokens and trivia to their original source line numbers.

推荐答案

SourceText 已经跟踪以 Lines 属性结尾的行.您可以使用类似于 GetLineAndOffset

The SourceText already tracks the line ending in the Lines property. You can use something like the code in GetLineAndOffset

这篇关于将标记和琐事映射到行号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆