如何通过Roslyn获取与Visual Studio一致的代码列号?
Roslyn获取VS风格列号的解决方案
一、计算VS显示风格的列号
Roslyn返回的Character是零基字符索引(制表符算1个字符),但VS的Col是基于显示宽度的1基列号——制表符会被替换成你设置的空格数(你这里是5)。要拿到准确的VS列号,得按以下步骤来:
先拿到目标行的原始文本
用syntaxTree.GetText(cancellationToken).Lines[lineNumber]获取对应行的内容,这里的lineNumber是FileLinePositionSpan.StartLinePosition.Line(零基)。计算行首到目标位置的显示宽度
遍历该行从开头到Character索引(不包含该索引)的每个字符:- 普通字符:宽度加1
- 制表符:宽度加你VS里设置的制表符空格数(比如你的5)
转成VS的1基列号
最后把计算出的显示宽度加1,就是VS里显示的Col值。
代码示例:
var linePos = fileLineSpan.StartLinePosition; var lineText = syntaxTree.GetText(cancellationToken).Lines[linePos.Line].ToString(); int tabWidth = 5; // 对应你VS里的制表符替换空格数 int displayWidth = 0; for (int i = 0; i < linePos.Character; i++) { if (lineText[i] == '\t') displayWidth += tabWidth; else displayWidth += 1; } int vsCol = displayWidth + 1; // 转成VS的1基列号
二、关于之前GetLineSpan和VS位置不匹配的情况
如果之前出现过这种不一致,大概率是这几个原因:
- 文件行尾格式或编码差异:比如文件用了CRLF还是LF,偶尔会导致行位置计算偏差,但Roslyn一般能正确处理。
- 语法树和编辑状态不同步:源生成器用的语法树可能是保存后的文件版本,而VS显示的是你正在编辑的未保存内容,位置自然对不上。
- 预处理指令影响:比如
#region、#if这类指令,可能让Roslyn的语法树解析和VS的显示结构有差异,但这种情况不多见。
要是后续复现了,先查这两点:
- 确认源生成器里的
syntaxTree是不是对应VS当前打开的最新文件版本 - 对比
syntaxTree.GetText()拿到的文本和VS里的原始文本是不是完全一致
内容的提问来源于stack exchange,提问作者Christopher J. Grace
相关产品推荐
相关产品推荐

