可以通过使用标记器捕获注释将它们合并回生成的源代码来保留它们。
给定一个程序变量中的玩具程序,我们可以演示 cmets 如何在 AST 中丢失:
import ast
program = """
# This comment lost
p1v = 4 + 4
p1l = ['a', # Implicit line joining comment for a lost
'b'] # Ending comment for b lost
def p1f(x):
"p1f docstring"
# Comment in function p1f lost
return x
print(p1f(p1l), p1f(p1v))
"""
tree = ast.parse(program)
print('== Full program code:')
print(ast.unparse(tree))
输出显示所有 cmets 消失:
== Full program code:
p1v = 4 + 4
p1l = ['a', 'b']
def p1f(x):
"""p1f docstring"""
return x
print(p1f(p1l), p1f(p1v))
但是,如果我们使用分词器扫描 cmets,我们可以
使用它来合并 cmets:
from io import StringIO
import tokenize
def scan_comments(source):
""" Scan source code file for relevant comments
"""
# Find token for comments
for k,v in tokenize.tok_name.items():
if v == 'COMMENT':
comment = k
break
comtokens = []
with StringIO(source) as f:
tokens = tokenize.generate_tokens(f.readline)
for token in tokens:
if token.type != comment:
continue
comtokens += [token]
return comtokens
comtokens = scan_comments(program)
print('== Comment after p1l[0]\n\t', comtokens[1])
输出(编辑为分割长线):
== Comment after p1l[0]
TokenInfo(type=60 (COMMENT),
string='# Implicit line joining comment for a lost',
start=(4, 12), end=(4, 54),
line="p1l = ['a', # Implicit line joining comment for a lost\n")
使用ast.unparse() 的略微修改版本,替换
方法 maybe_newline() 和 traverse() 修改版本,
你应该能够在他们的所有 cmets 中合并回来
大致位置,使用评论中的位置信息
扫描仪(开始变量),结合来自
AST;大多数节点都有lineno 属性。
不完全是。参见例如列表变量赋值。这
源代码分为两行,但ast.unparse()
只生成一行(参见第二个代码段中的输出)。
另外,您需要确保更新 AST 中的位置信息
添加代码后使用ast.increment_lineno()。
似乎有更多的电话
maybe_newline() 可能需要在库代码(或其
替换)。