-
-
Notifications
You must be signed in to change notification settings - Fork 186
Expand file tree
/
Copy pathsafe-names.ts
More file actions
113 lines (98 loc) · 2.86 KB
/
Copy pathsafe-names.ts
File metadata and controls
113 lines (98 loc) · 2.86 KB
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import * as ts from "typescript";
import { CompilerOptions, LuaTarget } from "../..";
import { TransformationContext } from "../context";
import { invalidAmbientIdentifierName } from "./diagnostics";
import { isSymbolExported } from "./export";
import { isAmbientNode } from "./typescript";
export const shouldAllowUnicode = (options: CompilerOptions) => options.luaTarget === LuaTarget.LuaJIT;
export const isValidLuaIdentifier = (name: string, options: CompilerOptions) =>
!luaKeywords.has(name) &&
(shouldAllowUnicode(options)
? /^[a-zA-Z_\u007F-\uFFFD][a-zA-Z0-9_\u007F-\uFFFD]*$/
: /^[a-zA-Z_][a-zA-Z0-9_]*$/
).test(name);
export const luaKeywords: ReadonlySet<string> = new Set([
"and",
"bit",
"bit32",
"break",
"do",
"else",
"elseif",
"end",
"false",
"for",
"function",
"goto",
"if",
"in",
"local",
"nil",
"not",
"or",
"repeat",
"return",
"then",
"true",
"until",
"while",
]);
const luaBuiltins: ReadonlySet<string> = new Set([
"_G",
"assert",
"coroutine",
"debug",
"error",
"ipairs",
"math",
"pairs",
"pcall",
"print",
"rawget",
"repeat",
"require",
"self",
"string",
"table",
"tostring",
"type",
"unpack",
]);
export const isUnsafeName = (name: string, options: CompilerOptions) =>
!isValidLuaIdentifier(name, options) || luaBuiltins.has(name);
function checkName(context: TransformationContext, name: string, node: ts.Node): boolean {
const isInvalid = !isValidLuaIdentifier(name, context.options);
if (isInvalid) {
// Empty identifier is a TypeScript error
if (name !== "") {
context.diagnostics.push(invalidAmbientIdentifierName(node, name));
}
}
return isInvalid;
}
export function hasUnsafeSymbolName(
context: TransformationContext,
symbol: ts.Symbol,
tsOriginal: ts.Identifier
): boolean {
const isAmbient = symbol.declarations?.some(d => isAmbientNode(d)) ?? false;
// Catch ambient declarations of identifiers with bad names
if (isAmbient && checkName(context, symbol.name, tsOriginal)) {
return true;
}
// only unsafe when non-ambient and not exported
return isUnsafeName(symbol.name, context.options) && !isAmbient && !isSymbolExported(context, symbol);
}
export function hasUnsafeIdentifierName(
context: TransformationContext,
identifier: ts.Identifier,
symbol: ts.Symbol | undefined
): boolean {
if (symbol) {
return hasUnsafeSymbolName(context, symbol, identifier);
}
return checkName(context, identifier.text, identifier);
}
const fixInvalidLuaIdentifier = (name: string) =>
name.replace(/[^a-zA-Z0-9_]/g, c => `_${c.charCodeAt(0).toString(16).toUpperCase()}`);
export const createSafeName = (name: string) => "____" + fixInvalidLuaIdentifier(name);