deploy: v0.12 存档迁移+考古日志滚动条

This commit is contained in:
2026-06-24 03:04:38 +00:00
parent 4831505ef9
commit b4c6111516
58986 changed files with 7569452 additions and 31667 deletions
+231
View File
@@ -0,0 +1,231 @@
# Operator precedence
a + b * c - d**3
a or b > 2 and c or d == None
a + b | c & d
==>
Script(
ExpressionStatement(BinaryExpression(BinaryExpression(VariableName, ArithOp,
BinaryExpression(VariableName, ArithOp, VariableName)), ArithOp, BinaryExpression(VariableName, ArithOp, Number))),
ExpressionStatement(BinaryExpression(BinaryExpression(VariableName, or,
BinaryExpression(BinaryExpression(VariableName, CompareOp, Number), and, VariableName)),
or, BinaryExpression(VariableName, CompareOp, None))),
ExpressionStatement(BinaryExpression(BinaryExpression(VariableName, ArithOp, VariableName), BitOp,
BinaryExpression(VariableName, BitOp, VariableName))))
# Strings
'foo' "bar"
b'baz'
'''long string
on two lines'''
"""also with double
quotes"""
==>
Script(ExpressionStatement(ContinuedString(String, String)),
ExpressionStatement(String),
ExpressionStatement(String),
ExpressionStatement(String))
# Raw string
r"foo\"" + r'\\'
==>
Script(ExpressionStatement(BinaryExpression(String,ArithOp,String)))
# Bracketed continued string
print('00300:'
'03630:')
==>
Script(ExpressionStatement(CallExpression(VariableName, ArgList(ContinuedString(String, String)))))
# Format strings
f'hello{22} abc\' {{ }} {d-1}'
f"double\" {quoted !s}"
f"""big long format
{string :foo}"""
f'''well {{ \x }} {2 :{bar}}'''
f"""one"{two}"three"""
f'{user=!s} {delta.days=:,d}'
==>
Script(ExpressionStatement(FormatString(FormatReplacement(Number),Escape,
FormatReplacement(BinaryExpression(VariableName, ArithOp, Number)))),
ExpressionStatement(FormatString(Escape,FormatReplacement(VariableName, FormatConversion))),
ExpressionStatement(FormatString(FormatReplacement(VariableName, FormatSpec))),
ExpressionStatement(FormatString(Escape,FormatReplacement(Number, FormatSpec(FormatReplacement(VariableName))))),
ExpressionStatement(FormatString(FormatReplacement(VariableName))),
ExpressionStatement(FormatString(
FormatReplacement(VariableName,FormatSelfDoc,FormatConversion),
FormatReplacement(MemberExpression(VariableName,PropertyName),FormatSelfDoc,FormatSpec))))
# Nested quote types
f"a{'b'}c"
==>
Script(ExpressionStatement(FormatString(FormatReplacement(String))))
# Lambda
something.map(lambda x: x + 1)
foo = lambda a, b = 0: a ^ b
==>
Script(
ExpressionStatement(CallExpression(MemberExpression(VariableName, PropertyName), ArgList(
LambdaExpression(lambda, ParamList(VariableName), BinaryExpression(VariableName, ArithOp, Number))))),
AssignStatement(VariableName, AssignOp, LambdaExpression(lambda, ParamList(VariableName, VariableName, AssignOp, Number),
BinaryExpression(VariableName, BitOp, VariableName))))
# Member expressions
x[1]
x.foo
x.if.True
==>
Script(
ExpressionStatement(MemberExpression(VariableName, Number)),
ExpressionStatement(MemberExpression(VariableName, PropertyName)),
ExpressionStatement(MemberExpression(MemberExpression(VariableName, PropertyName), PropertyName)))
# Call expressions
foo(x, y, **z) + bar(blah=20)
==>
Script(ExpressionStatement(BinaryExpression(
CallExpression(VariableName, ArgList(VariableName, VariableName, VariableName)),
ArithOp,
CallExpression(VariableName, ArgList(VariableName, AssignOp, Number)))))
# Collection expressions
[True, False, None]
{foo: 22, bar: False, **other}
{1, 2, 3}
(3)
(3,)
(3, 4)
==>
Script(
ExpressionStatement(ArrayExpression(Boolean, Boolean, None)),
ExpressionStatement(DictionaryExpression(VariableName, Number, VariableName, Boolean, VariableName)),
ExpressionStatement(SetExpression(Number, Number, Number)),
ExpressionStatement(ParenthesizedExpression(Number)),
ExpressionStatement(TupleExpression(Number)),
ExpressionStatement(TupleExpression(Number, Number)))
# Comprehension expressions
[i + 1 for i in range(1, 10) if x % 2 == 0]
(x for x in [3, 4])
{key: value for (key, value) in blah}
{a - b for a in foo for b in bar}
==>
Script(
ExpressionStatement(ArrayComprehensionExpression(
BinaryExpression(VariableName, ArithOp, Number),
for VariableName in CallExpression(VariableName, ArgList(Number, Number)),
if BinaryExpression(BinaryExpression(VariableName, ArithOp, Number), CompareOp, Number))),
ExpressionStatement(ComprehensionExpression(
VariableName, for, VariableName, in, ArrayExpression(Number, Number))),
ExpressionStatement(DictionaryComprehensionExpression(
VariableName, VariableName, for, TupleExpression(VariableName, VariableName) in VariableName)),
ExpressionStatement(SetComprehensionExpression(
BinaryExpression(VariableName, ArithOp, VariableName), for, VariableName, in, VariableName,
for, VariableName, in, VariableName)))
# Yield expressions
def foo():
yield 1
return 1 + (yield 2)
==>
Script(FunctionDefinition(def, VariableName, ParamList, Body(
YieldStatement(yield, Number),
ReturnStatement(return, BinaryExpression(Number, ArithOp, ParenthesizedExpression(YieldExpression(yield, Number)))))))
# Unary expressions
[-1, +2 * 3, ~2**2]
==>
Script(ExpressionStatement(ArrayExpression(
UnaryExpression(ArithOp, Number),
BinaryExpression(UnaryExpression(ArithOp, Number), ArithOp, Number),
UnaryExpression(BitOp, BinaryExpression(Number, ArithOp, Number)))))
# Await
await something()
==>
Script(ExpressionStatement(AwaitExpression(await, CallExpression(VariableName, ArgList))))
# Newlines in brackets
x = [
1, 2,
# And
3, 4,
]
==>
Script(AssignStatement(VariableName, AssignOp, ArrayExpression(Number, Number, Comment, Number, Number)))
# Too many commas in brackets
x = [
1, 2,,
]
==>
Script(AssignStatement(VariableName, AssignOp, ArrayExpression(Number, Number, ⚠)))
# Conditional expression
x = 5 if True else 1 if False else 0
==>
Script(AssignStatement(VariableName, AssignOp, ConditionalExpression(Number, if, Boolean, else,
ConditionalExpression(Number, if, Boolean, else, Number))))
# Exponent is R-to-L associative
2 ** 3 ** 2
==>
Script(ExpressionStatement(BinaryExpression(
Number,ArithOp("**"),
BinaryExpression(Number,ArithOp("**"),Number))))
+442
View File
@@ -0,0 +1,442 @@
# Function definition
def foo():
pass
def bar(a: str, b = 22, **c) -> num:
pass
==>
Script(
FunctionDefinition(def,VariableName,ParamList,Body(PassStatement(pass))),
FunctionDefinition(def,VariableName,ParamList(VariableName, TypeDef(VariableName), VariableName, AssignOp, Number, VariableName),
TypeDef(VariableName), Body(PassStatement(pass))))
# Single-line function definition
def foo(a, b): return a + b
==>
Script(FunctionDefinition(def,VariableName,ParamList(VariableName, VariableName),
Body(ReturnStatement(return, BinaryExpression(VariableName, ArithOp, VariableName)))))
# Return with no body
def foo(a, b):
a = b
return
==>
Script(FunctionDefinition(def,VariableName,ParamList(VariableName, VariableName),
Body(AssignStatement(VariableName, AssignOp, VariableName), ReturnStatement(return))))
# Conditional
if a: b()
if 1 + 3:
pass
elif 55 < 2:
pass
else:
pass
==>
Script(
IfStatement(if, VariableName, Body(ExpressionStatement(CallExpression(VariableName, ArgList))))
IfStatement(if, BinaryExpression(Number, ArithOp, Number), Body(PassStatement(pass)),
elif, BinaryExpression(Number, CompareOp, Number), Body(PassStatement(pass)),
else, Body(PassStatement(pass))))
# Assignment
a = 4
b: str = "hi"
c, d, e = None
f = g = False
h += 1
==>
Script(
AssignStatement(VariableName, AssignOp, Number),
AssignStatement(VariableName, TypeDef(VariableName), AssignOp, String),
AssignStatement(VariableName, VariableName, VariableName, AssignOp, None),
AssignStatement(VariableName, AssignOp, VariableName, AssignOp, Boolean),
UpdateStatement(VariableName, UpdateOp, Number))
# For loops
for a, b in woop():
doStuff(b, a)
==>
Script(ForStatement(for, VariableName, VariableName, in CallExpression(VariableName, ArgList),
Body(ExpressionStatement(CallExpression(VariableName, ArgList(VariableName, VariableName))))))
# Try statements
try:
pass
except SomeException as e:
pass
except OtherException:
pass
else:
pass
finally:
pass
==>
Script(TryStatement(
try, Body(PassStatement(pass)),
except, VariableName, as, VariableName, Body(PassStatement(pass)),
except VariableName, Body(PassStatement(pass)),
else Body(PassStatement(pass)),
finally Body(PassStatement(pass))))
# With statements
with open("x") as file:
pass
async with foo as bar:
pass
==>
Script(
WithStatement(with, CallExpression(VariableName, ArgList(String)), as, VariableName, Body(PassStatement(pass))),
WithStatement(async, with, VariableName, as, VariableName, Body(PassStatement(pass))))
# Class definition
class Foo:
prop = 0
def __init__(self):
pass
def plus(self):
self.prop += 1
class Bar(Foo): pass
==>
Script(
ClassDefinition(class, VariableName, Body(
AssignStatement(VariableName, AssignOp, Number),
FunctionDefinition(def, VariableName, ParamList(VariableName), Body(PassStatement(pass))),
FunctionDefinition(def, VariableName, ParamList(VariableName), Body(
UpdateStatement(MemberExpression(VariableName, PropertyName), UpdateOp, Number))))),
ClassDefinition(class, VariableName, ArgList(VariableName), Body(PassStatement(pass))))
# Scope statements
global a
nonlocal b, c
==>
Script(
ScopeStatement(global, VariableName),
ScopeStatement(nonlocal, VariableName, VariableName))
# Decorators
@Something.X
def f(): pass
@Other(arg1, arg2)
class C: pass
==>
Script(
DecoratedStatement(Decorator(At, VariableName, VariableName),
FunctionDefinition(def, VariableName, ParamList, Body(PassStatement(pass)))),
DecoratedStatement(Decorator(At, VariableName, ArgList(VariableName, VariableName)),
ClassDefinition(class, VariableName, Body(PassStatement(pass)))))
# Small statements
def x(): return 5
raise Exception("woop")
while False:
break
continue
assert 1 == 2
del x[2]
==>
Script(
FunctionDefinition(def, VariableName, ParamList, Body(ReturnStatement(return, Number))),
RaiseStatement(raise, CallExpression(VariableName, ArgList(String))),
WhileStatement(while, Boolean, Body(BreakStatement(break), ContinueStatement(continue))),
AssertStatement(assert, BinaryExpression(Number, CompareOp, Number)),
DeleteStatement(del, MemberExpression(VariableName, Number)))
# Import statements
import datetime
from something.other import one, two
==>
Script(
ImportStatement(import, VariableName),
ImportStatement(from, VariableName, VariableName, import VariableName, VariableName))
# One-line small statements
x; y(); z = 2
raise "oh"
==>
Script(
StatementGroup(
ExpressionStatement(VariableName),
ExpressionStatement(CallExpression(VariableName, ArgList)),
AssignStatement(VariableName, AssignOp, Number)),
RaiseStatement(raise, String))
# Nested bodies
def x():
ok
if not ok:
while True:
one
two
three
if None:
four
else:
five
six
seven
==>
Script(
FunctionDefinition(def, VariableName, ParamList, Body(
ExpressionStatement(VariableName),
IfStatement(if, UnaryExpression(not, VariableName), Body(
WhileStatement(while, Boolean, Body(
ExpressionStatement(VariableName),
ExpressionStatement(VariableName))))),
ExpressionStatement(VariableName),
IfStatement(if, None, Body(
ExpressionStatement(VariableName)
), else, Body(
ExpressionStatement(VariableName))),
ExpressionStatement(VariableName))),
ExpressionStatement(VariableName))
# Empty and commented lines
if None:
one
two
four
# comment
five
six
==>
Script(
IfStatement(if, None, Body(
ExpressionStatement(VariableName),
ExpressionStatement(VariableName),
ExpressionStatement(VariableName),
Comment,
ExpressionStatement(VariableName))),
ExpressionStatement(VariableName))
# Script ending in a comment
x = 1
# End
==>
Script(AssignStatement(VariableName,AssignOp,Number),Comment)
# Escaped newlines
x = 1 + \
2
==>
Script(AssignStatement(VariableName, AssignOp, BinaryExpression(Number, ArithOp, Number)))
# Python 2 compatibility
print "hi"
print(print.something)
try:
raise Exception, "foo"
except Exception, foo:
pass
==>
Script(
PrintStatement(print, String),
ExpressionStatement(CallExpression(VariableName, ArgList(MemberExpression(VariableName, PropertyName)))),
TryStatement(try, Body(RaiseStatement(raise, VariableName, String)),
except, VariableName, VariableName, Body(PassStatement(pass))))
# Require indentation on body
def foo():
pass
==>
Script(FunctionDefinition(def,VariableName,ParamList,Body(⚠)), PassStatement(pass))
# Nested else
if a:
if b:
pass
else:
pass
==>
Script(IfStatement(if, VariableName, Body(
IfStatement(if, VariableName, Body(PassStatement(pass)))),
else, Body(PassStatement(pass))))
# Self not reserved
self = True
==>
Script(AssignStatement(VariableName,AssignOp,Boolean))
# Trailing whitespace in block
def x():
one
two
==>
Script(FunctionDefinition(def,VariableName,ParamList,Body(ExpressionStatement(VariableName),ExpressionStatement(VariableName))))
# Can handle tab indentation
class Employee:
first_name: str
last_name: str
def __init__(self, a):
self.first_name = a
self.last_name = a
==>
Script(ClassDefinition(class,VariableName,Body(
AssignStatement(VariableName,TypeDef(VariableName)),
AssignStatement(VariableName,TypeDef(VariableName)),
FunctionDefinition(def,VariableName,ParamList(VariableName,VariableName),Body(
AssignStatement(MemberExpression(VariableName,PropertyName),AssignOp,VariableName),
AssignStatement(MemberExpression(VariableName,PropertyName),AssignOp,VariableName))))))
# Parses match statements
match foo:
case 1:
pass
case Point("a", True) as z | a.b | {x: None, **y}:
pass
case [a, b, *rest] | (p, q):
pass
case (1, 2) if bar == 2:
pass
==>
Script(MatchStatement(match,VariableName,MatchBody(
MatchClause(case,
LiteralPattern(Number),
Body(PassStatement(pass))),
MatchClause(case,
OrPattern(
AsPattern(
ClassPattern(VariableName,PatternArgList(LiteralPattern(String),LiteralPattern(Boolean))),
as,VariableName),
LogicOp,
AttributePattern(VariableName,PropertyName),
LogicOp,
MappingPattern(VariableName,LiteralPattern(None),CapturePattern(VariableName))),
Body(PassStatement(pass))),
MatchClause(case,
OrPattern(SequencePattern(
CapturePattern(VariableName),
CapturePattern(VariableName),
StarPattern(CapturePattern(VariableName))),
LogicOp,
SequencePattern(CapturePattern(VariableName),CapturePattern(VariableName))),
Body(PassStatement(pass))),
MatchClause(case,
SequencePattern(LiteralPattern(Number),LiteralPattern(Number)),
Guard(if,BinaryExpression(VariableName,CompareOp,Number)),
Body(PassStatement(pass))))))
# Type Params
class ClassA[T: str]:
def method1(self) -> T:
pass
def func[**T](a: T, b: T) -> T:
pass
==>
Script(
ClassDefinition(class,VariableName,
TypeParamList(TypeParam(VariableName,TypeDef(":",VariableName))),
Body(FunctionDefinition(def,VariableName,ParamList(VariableName),TypeDef(VariableName),
Body(PassStatement(pass))))),
FunctionDefinition(def,VariableName,TypeParamList(TypeParam(VariableName)),
ParamList(VariableName,TypeDef(VariableName),VariableName,TypeDef(VariableName)),
TypeDef(VariableName),
Body(PassStatement(pass))))
# Type Definition
type Point = tuple[float, float]
==>
Script(TypeDefinition(type,VariableName,MemberExpression(VariableName,VariableName,",",VariableName)))
# Rest arg with type
def f(*args: tuple[int]) -> int:
return 1
==>
Script(FunctionDefinition(def,VariableName,
ParamList(VariableName,TypeDef(MemberExpression(VariableName,VariableName))),
TypeDef(VariableName),
Body(ReturnStatement(return,Number))))
+33
View File
@@ -0,0 +1,33 @@
import {parser} from "../dist/index.js"
import {fileTests} from "@lezer/generator/dist/test"
import {Tree, TreeFragment} from "@lezer/common"
describe("Incremental parsing", () => {
// See https://github.com/codemirror/codemirror.next/issues/394
it("doesn't reuse statements in the wrong body", () => {
let input = `class StreamWriter:
def __init__(self):
pass
def a():
pass
def b(self):
""" ${"big block comment to fill up the reuse size quota\n ".repeat(150)} """
pass
`
let ast = parser.parse(input)
let at = input.indexOf("pass")
input = input.slice(0, at) + " " + input.slice(at)
let cache = TreeFragment.applyChanges(TreeFragment.addTree(ast), [{fromA: at, toA: at, fromB: at, toB: at + 1}])
let ast2 = parser.parse(input, cache)
if (ast2.toString() != ast.toString()) throw new Error("Malformed tree")
let lastFunc = ast => {
let cur = ast.cursor(ast.length)
while (cur.type.name != "FunctionDefinition") cur.prev()
return cur.tree
}
if (lastFunc(ast) != lastFunc(ast2)) throw new Error("No reuse")
})
})
+17
View File
@@ -0,0 +1,17 @@
import {parser} from "../dist/index.js"
import {fileTests} from "@lezer/generator/dist/test"
import * as fs from "fs"
import * as path from "path"
import {fileURLToPath} from "url"
let caseDir = path.dirname(fileURLToPath(import.meta.url))
for (let file of fs.readdirSync(caseDir)) {
if (!/\.txt$/.test(file)) continue
let name = /^[^\.]*/.exec(file)[0]
describe(name, () => {
for (let {name, run} of fileTests(fs.readFileSync(path.join(caseDir, file), "utf8"), file))
it(name, () => run(parser))
})
}