turbo-editors/turbo-pythonpublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-python.git
git clone ssh://git@rickub.com/turbo-editors/turbo-python.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

📦 Turbo Python 6fc62ea · on main · k33g · 7h ago
reference_test.go · 90 lines · 3.5 KBGo Blame HistoryRaw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package pythonlang

import (
	"strings"
	"testing"

	"rickub.com/turbo-editors/turbo-core/syntax"
)

// TestTheLanguagesReferenceIsTrue holds docs/*/reference/languages.md to the
// scanner. Every row of its Python table that no other test here covers is
// checked, so a reference claim and the code cannot drift apart quietly.
//
// The last three cases document *limitations* rather than features — an
// all-capital class name read as a constant, `type` read as the builtin rather
// than as a soft keyword, an f-string's braces left inside the string. The
// reference says each of those in so many words, and these rows are what stops
// somebody "fixing" one without also fixing the sentence.
func TestTheLanguagesReferenceIsTrue(t *testing.T) {
	tests := []struct {
		src  string
		word string
		want syntax.Class
	}{
		{"assert x is not None", "assert", syntax.ClassKeyword},
		{"nonlocal counter", "nonlocal", syntax.ClassKeyword},
		{"async def f() -> None:\n    pass\n", "async", syntax.ClassKeyword},
		{"x = NotImplemented", "NotImplemented", syntax.ClassConstant},
		{"x = Ellipsis", "Ellipsis", syntax.ClassConstant},
		{"if __debug__:\n    pass\n", "__debug__", syntax.ClassConstant},
		{"x: frozenset = frozenset()", "frozenset", syntax.ClassType},
		{"x: memoryview = m", "memoryview", syntax.ClassType},
		{"x = isinstance(v, int)", "isinstance", syntax.ClassBuiltin},
		{"x = sorted(v)", "sorted", syntax.ClassBuiltin},
		{"def f(cls) -> None:\n    pass\n", "cls", syntax.ClassBuiltin},
		{"x = obj.__name__", "__name__", syntax.ClassBuiltin},
		{`x = rb"raw bytes"`, `rb"raw bytes"`, syntax.ClassString},
		{`x = BR"raw bytes"`, `BR"raw bytes"`, syntax.ClassString},
		{`x = u"text"`, `u"text"`, syntax.ClassString},
		{"x = 0o17", "0o17", syntax.ClassNumber},
		{"x = 0b1010", "0b1010", syntax.ClassNumber},
		{"x = 3j", "3j", syntax.ClassNumber},
		{"x = 1E+7", "1E+7", syntax.ClassNumber},
		{"#!/usr/bin/env python3", "#!/usr/bin/env python3", syntax.ClassComment},
		{"@property\ndef x(self):\n    pass\n", "@property", syntax.ClassAttribute},
		{"if (n := f()) > 1:\n    pass\n", ":=", syntax.ClassOperator},
		{"d = {1: 2}", ":", syntax.ClassPunctuation},
		{"x = a @ b", "@", syntax.ClassOperator},
		{"x = 1 + \\", "\\", syntax.ClassPunctuation},
		{"x = [1, 2]", "[", syntax.ClassPunctuation},

		// The documented limitations.
		{"HTTP = 1", "HTTP", syntax.ClassConstant},
		{"type Alias = int", "type", syntax.ClassType},
		{"match value:  # dispatch\n", "match", syntax.ClassIdentifier},
	}

	for _, test := range tests {
		t.Run(test.word, func(t *testing.T) {
			index := strings.Index(test.src, test.word)
			if index < 0 {
				t.Fatalf("%q not in %q", test.word, test.src)
			}
			got, ok := classAt(Highlight(test.src), 0, index)
			if !ok || got != test.want {
				t.Errorf("%q in %q is %v (covered %v), want %v", test.word, test.src, got, ok, test.want)
			}
		})
	}
}

// The reference's Python table says the class `char` is produced by nothing
// here, because Python has no character type. That is a claim about every span
// the scanner can ever emit, so it is checked over a file that uses every
// construct the table names.
func TestTheScannerNeverProducesACharacterClass(t *testing.T) {
	const src = "#!/usr/bin/env python3\n" +
		"x = 'single'\n" +
		"y = \"double\"\n" +
		"z = b'bytes'\n" +
		"w = '''triple'''\n"

	for line, spans := range Highlight(src) {
		for _, span := range spans {
			if span.Class == syntax.ClassChar {
				t.Errorf("line %d holds a char span at %d; Python has no character literal", line, span.Start)
			}
		}
	}
}