Skip to content

Commit a92a86e

Browse files
committed
fixes
1 parent ada926c commit a92a86e

2 files changed

Lines changed: 141 additions & 194 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "typescript-to-lua",
3-
"version": "1.19.2",
3+
"version": "1.19.3",
44
"description": "A generic TypeScript to Lua transpiler. Write your code in TypeScript and publish Lua!",
55
"repository": "https://github.com/TypeScriptToLua/TypeScriptToLua",
66
"homepage": "https://typescripttolua.github.io/",
Lines changed: 140 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -1,234 +1,181 @@
11
import * as ts from "typescript";
22
import { CompilerOptions } from "../../CompilerOptions";
33
import { TransformationContext } from "../context";
4-
import {
5-
AnnotationKind,
6-
getFileAnnotations,
7-
getNodeAnnotations,
8-
} from "./annotations";
9-
import {
10-
findFirstNodeAbove,
11-
getAllCallSignatures,
12-
inferAssignedType,
13-
} from "./typescript";
4+
import { AnnotationKind, getFileAnnotations, getNodeAnnotations } from "./annotations";
5+
import { findFirstNodeAbove, getAllCallSignatures, inferAssignedType } from "./typescript";
146

157
export enum ContextType {
16-
None = 0,
17-
Void = 1 << 0,
18-
NonVoid = 1 << 1,
19-
Mixed = Void | NonVoid,
8+
None = 0,
9+
Void = 1 << 0,
10+
NonVoid = 1 << 1,
11+
Mixed = Void | NonVoid,
2012
}
2113

2214
function hasNoSelfAncestor(declaration: ts.Declaration): boolean {
23-
const scopeDeclaration = findFirstNodeAbove(
24-
declaration,
25-
(node): node is ts.SourceFile | ts.ModuleDeclaration =>
26-
ts.isSourceFile(node) || ts.isModuleDeclaration(node),
27-
);
28-
29-
if (!scopeDeclaration) {
30-
return false;
31-
} else if (ts.isSourceFile(scopeDeclaration)) {
32-
return getFileAnnotations(scopeDeclaration).has(
33-
AnnotationKind.NoSelfInFile,
15+
const scopeDeclaration = findFirstNodeAbove(
16+
declaration,
17+
(node): node is ts.SourceFile | ts.ModuleDeclaration => ts.isSourceFile(node) || ts.isModuleDeclaration(node)
3418
);
35-
} else if (getNodeAnnotations(scopeDeclaration).has(AnnotationKind.NoSelf)) {
36-
return true;
37-
} else {
38-
return hasNoSelfAncestor(scopeDeclaration);
39-
}
19+
20+
if (!scopeDeclaration) {
21+
return false;
22+
} else if (ts.isSourceFile(scopeDeclaration)) {
23+
return getFileAnnotations(scopeDeclaration).has(AnnotationKind.NoSelfInFile);
24+
} else if (getNodeAnnotations(scopeDeclaration).has(AnnotationKind.NoSelf)) {
25+
return true;
26+
} else {
27+
return hasNoSelfAncestor(scopeDeclaration);
28+
}
4029
}
4130

42-
function getExplicitThisParameter(
43-
signatureDeclaration: ts.SignatureDeclaration,
44-
): ts.ParameterDeclaration | undefined {
45-
const param = signatureDeclaration.parameters[0];
46-
if (
47-
param && ts.isIdentifier(param.name) &&
48-
ts.identifierToKeywordKind(param.name) === ts.SyntaxKind.ThisKeyword
49-
) {
50-
return param;
51-
}
31+
function getExplicitThisParameter(signatureDeclaration: ts.SignatureDeclaration): ts.ParameterDeclaration | undefined {
32+
const param = signatureDeclaration.parameters[0];
33+
if (param && ts.isIdentifier(param.name) && ts.identifierToKeywordKind(param.name) === ts.SyntaxKind.ThisKeyword) {
34+
return param;
35+
}
5236
}
5337

54-
const signatureDeclarationContextTypes = new WeakMap<
55-
ts.SignatureDeclaration,
56-
ContextType
57-
>();
38+
const signatureDeclarationContextTypes = new WeakMap<ts.SignatureDeclaration, ContextType>();
5839

5940
export function getDeclarationContextType(
60-
context: TransformationContext,
61-
signatureDeclaration: ts.SignatureDeclaration,
41+
context: TransformationContext,
42+
signatureDeclaration: ts.SignatureDeclaration
6243
): ContextType {
63-
const known = signatureDeclarationContextTypes.get(signatureDeclaration);
64-
if (known !== undefined) return known;
65-
const contextType = computeDeclarationContextType(
66-
context,
67-
signatureDeclaration,
68-
);
69-
signatureDeclarationContextTypes.set(signatureDeclaration, contextType);
70-
return contextType;
44+
const known = signatureDeclarationContextTypes.get(signatureDeclaration);
45+
if (known !== undefined) return known;
46+
const contextType = computeDeclarationContextType(context, signatureDeclaration);
47+
signatureDeclarationContextTypes.set(signatureDeclaration, contextType);
48+
return contextType;
7149
}
7250

73-
function computeDeclarationContextType(
74-
context: TransformationContext,
75-
signatureDeclaration: ts.SignatureDeclaration,
76-
) {
77-
const thisParameter = getExplicitThisParameter(signatureDeclaration);
78-
if (thisParameter) {
79-
// Explicit 'this'
80-
return thisParameter.type &&
81-
thisParameter.type.kind === ts.SyntaxKind.VoidKeyword
82-
? ContextType.Void
83-
: ContextType.NonVoid;
84-
}
85-
86-
// noSelf declaration on function signature
87-
if (getNodeAnnotations(signatureDeclaration).has(AnnotationKind.NoSelf)) {
88-
return ContextType.Void;
89-
}
90-
91-
if (
92-
ts.isMethodSignature(signatureDeclaration) ||
93-
ts.isMethodDeclaration(signatureDeclaration) ||
94-
ts.isConstructSignatureDeclaration(signatureDeclaration) ||
95-
ts.isConstructorDeclaration(signatureDeclaration) ||
96-
(signatureDeclaration.parent &&
97-
ts.isPropertyDeclaration(signatureDeclaration.parent)) ||
98-
(signatureDeclaration.parent &&
99-
ts.isPropertySignature(signatureDeclaration.parent))
100-
) {
101-
// Class/interface methods only respect @noSelf on their parent
102-
const scopeDeclaration = findFirstNodeAbove(
103-
signatureDeclaration,
104-
(n): n is ts.ClassLikeDeclaration | ts.InterfaceDeclaration =>
105-
ts.isClassDeclaration(n) || ts.isClassExpression(n) ||
106-
ts.isInterfaceDeclaration(n),
107-
);
51+
function computeDeclarationContextType(context: TransformationContext, signatureDeclaration: ts.SignatureDeclaration) {
52+
const thisParameter = getExplicitThisParameter(signatureDeclaration);
53+
if (thisParameter) {
54+
// Explicit 'this'
55+
return thisParameter.type && thisParameter.type.kind === ts.SyntaxKind.VoidKeyword
56+
? ContextType.Void
57+
: ContextType.NonVoid;
58+
}
10859

109-
if (
110-
scopeDeclaration !== undefined &&
111-
getNodeAnnotations(scopeDeclaration).has(AnnotationKind.NoSelf)
112-
) {
113-
return ContextType.Void;
60+
// noSelf declaration on function signature
61+
if (getNodeAnnotations(signatureDeclaration).has(AnnotationKind.NoSelf)) {
62+
return ContextType.Void;
11463
}
11564

116-
return ContextType.NonVoid;
117-
}
118-
119-
// When using --noImplicitSelf and the signature is defined in a file targeted by the program apply the @noSelf rule.
120-
const program = context.program;
121-
const options = program.getCompilerOptions() as CompilerOptions;
122-
if (options.noImplicitSelf) {
123-
const sourceFile = program.getSourceFile(
124-
signatureDeclaration.getSourceFile().fileName,
125-
);
12665
if (
127-
sourceFile !== undefined &&
128-
!program.isSourceFileDefaultLibrary(sourceFile) &&
129-
!program.isSourceFileFromExternalLibrary(sourceFile)
66+
ts.isMethodSignature(signatureDeclaration) ||
67+
ts.isMethodDeclaration(signatureDeclaration) ||
68+
ts.isConstructSignatureDeclaration(signatureDeclaration) ||
69+
ts.isConstructorDeclaration(signatureDeclaration) ||
70+
(signatureDeclaration.parent && ts.isPropertyDeclaration(signatureDeclaration.parent)) ||
71+
(signatureDeclaration.parent && ts.isPropertySignature(signatureDeclaration.parent))
13072
) {
131-
return ContextType.Void;
73+
// Class/interface methods only respect @noSelf on their parent
74+
const scopeDeclaration = findFirstNodeAbove(
75+
signatureDeclaration,
76+
(n): n is ts.ClassLikeDeclaration | ts.InterfaceDeclaration =>
77+
ts.isClassDeclaration(n) || ts.isClassExpression(n) || ts.isInterfaceDeclaration(n)
78+
);
79+
80+
if (scopeDeclaration !== undefined && getNodeAnnotations(scopeDeclaration).has(AnnotationKind.NoSelf)) {
81+
return ContextType.Void;
82+
}
83+
84+
return ContextType.NonVoid;
13285
}
133-
}
13486

135-
if (options.disableSelfGlobal) {
136-
return ContextType.Void;
137-
}
87+
// When using --noImplicitSelf and the signature is defined in a file targeted by the program apply the @noSelf rule.
88+
const program = context.program;
89+
const options = program.getCompilerOptions() as CompilerOptions;
90+
if (options.noImplicitSelf) {
91+
const sourceFile = program.getSourceFile(signatureDeclaration.getSourceFile().fileName);
92+
if (
93+
sourceFile !== undefined &&
94+
!program.isSourceFileDefaultLibrary(sourceFile) &&
95+
!program.isSourceFileFromExternalLibrary(sourceFile)
96+
) {
97+
return ContextType.Void;
98+
}
99+
}
138100

139-
// Walk up to find @noSelf or @noSelfInFile
140-
if (hasNoSelfAncestor(signatureDeclaration)) {
141-
return ContextType.Void;
142-
}
101+
if (options.disableSelfGlobal) {
102+
return ContextType.Void;
103+
}
143104

144-
return ContextType.NonVoid;
105+
// Walk up to find @noSelf or @noSelfInFile
106+
if (hasNoSelfAncestor(signatureDeclaration)) {
107+
return ContextType.Void;
108+
}
109+
110+
return ContextType.NonVoid;
145111
}
146112

147113
function reduceContextTypes(contexts: ContextType[]): ContextType {
148-
let type = ContextType.None;
149-
for (const context of contexts) {
150-
type |= context;
151-
if (type === ContextType.Mixed) break;
152-
}
153-
return type;
114+
let type = ContextType.None;
115+
for (const context of contexts) {
116+
type |= context;
117+
if (type === ContextType.Mixed) break;
118+
}
119+
return type;
154120
}
155121

156-
function getSignatureDeclarations(
157-
context: TransformationContext,
158-
signature: ts.Signature,
159-
): ts.SignatureDeclaration[] {
160-
if (signature.compositeSignatures) {
161-
return signature.compositeSignatures.flatMap((s) =>
162-
getSignatureDeclarations(context, s)
163-
);
164-
}
165-
166-
const signatureDeclaration = signature.getDeclaration();
167-
if (signatureDeclaration === undefined) {
168-
return [];
169-
}
170-
171-
let inferredType: ts.Type | undefined;
172-
if (
173-
ts.isMethodDeclaration(signatureDeclaration) &&
174-
ts.isObjectLiteralExpression(signatureDeclaration.parent) &&
175-
!getExplicitThisParameter(signatureDeclaration)
176-
) {
177-
inferredType = context.checker.getContextualTypeForObjectLiteralElement(
178-
signatureDeclaration,
179-
);
180-
} else if (
181-
(ts.isFunctionExpression(signatureDeclaration) ||
182-
ts.isArrowFunction(signatureDeclaration)) &&
183-
!getExplicitThisParameter(signatureDeclaration)
184-
) {
185-
// Infer type of function expressions/arrow functions
186-
inferredType = inferAssignedType(context, signatureDeclaration);
187-
}
188-
189-
if (inferredType) {
190-
const inferredSignatures = getAllCallSignatures(inferredType);
191-
if (inferredSignatures.length > 0) {
192-
return inferredSignatures.map((s) => s.getDeclaration());
122+
function getSignatureDeclarations(context: TransformationContext, signature: ts.Signature): ts.SignatureDeclaration[] {
123+
if (signature.compositeSignatures) {
124+
return signature.compositeSignatures.flatMap(s => getSignatureDeclarations(context, s));
125+
}
126+
127+
const signatureDeclaration = signature.getDeclaration();
128+
if (signatureDeclaration === undefined) {
129+
return [];
193130
}
194-
}
195131

196-
return [signatureDeclaration];
132+
let inferredType: ts.Type | undefined;
133+
if (
134+
ts.isMethodDeclaration(signatureDeclaration) &&
135+
ts.isObjectLiteralExpression(signatureDeclaration.parent) &&
136+
!getExplicitThisParameter(signatureDeclaration)
137+
) {
138+
inferredType = context.checker.getContextualTypeForObjectLiteralElement(signatureDeclaration);
139+
} else if (
140+
(ts.isFunctionExpression(signatureDeclaration) || ts.isArrowFunction(signatureDeclaration)) &&
141+
!getExplicitThisParameter(signatureDeclaration)
142+
) {
143+
// Infer type of function expressions/arrow functions
144+
inferredType = inferAssignedType(context, signatureDeclaration);
145+
}
146+
147+
if (inferredType) {
148+
const inferredSignatures = getAllCallSignatures(inferredType);
149+
if (inferredSignatures.length > 0) {
150+
return inferredSignatures.map(s => s.getDeclaration());
151+
}
152+
}
153+
154+
return [signatureDeclaration];
197155
}
198156

199157
const typeContextTypes = new WeakMap<ts.Type, ContextType>();
200158

201-
export function getFunctionContextType(
202-
context: TransformationContext,
203-
type: ts.Type,
204-
): ContextType {
205-
const known = typeContextTypes.get(type);
206-
if (known !== undefined) return known;
207-
const contextType = computeFunctionContextType(context, type);
208-
typeContextTypes.set(type, contextType);
209-
return contextType;
159+
export function getFunctionContextType(context: TransformationContext, type: ts.Type): ContextType {
160+
const known = typeContextTypes.get(type);
161+
if (known !== undefined) return known;
162+
const contextType = computeFunctionContextType(context, type);
163+
typeContextTypes.set(type, contextType);
164+
return contextType;
210165
}
211166

212-
function computeFunctionContextType(
213-
context: TransformationContext,
214-
type: ts.Type,
215-
): ContextType {
216-
if (type.isTypeParameter()) {
217-
const constraint = type.getConstraint();
218-
if (constraint) return getFunctionContextType(context, constraint);
219-
}
220-
221-
const signatures = context.checker.getSignaturesOfType(
222-
type,
223-
ts.SignatureKind.Call,
224-
);
225-
if (signatures.length === 0) {
226-
return ContextType.None;
227-
}
228-
229-
return reduceContextTypes(
230-
signatures.flatMap((s) => getSignatureDeclarations(context, s)).map((s) =>
231-
getDeclarationContextType(context, s)
232-
),
233-
);
167+
function computeFunctionContextType(context: TransformationContext, type: ts.Type): ContextType {
168+
if (type.isTypeParameter()) {
169+
const constraint = type.getConstraint();
170+
if (constraint) return getFunctionContextType(context, constraint);
171+
}
172+
173+
const signatures = context.checker.getSignaturesOfType(type, ts.SignatureKind.Call);
174+
if (signatures.length === 0) {
175+
return ContextType.None;
176+
}
177+
178+
return reduceContextTypes(
179+
signatures.flatMap(s => getSignatureDeclarations(context, s)).map(s => getDeclarationContextType(context, s))
180+
);
234181
}

0 commit comments

Comments
 (0)