Skip to content

Commit f6a92c0

Browse files
authored
Remove phantom, metaExtension, extension, pureAbstract (#998)
And replace the deprecation warning with an error Progress on #953
1 parent 22e6019 commit f6a92c0

File tree

22 files changed

+113
-477
lines changed

22 files changed

+113
-477
lines changed

src/transformation/utils/diagnostics.ts

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,30 +58,6 @@ export const annotationInvalidArgumentCount = createErrorDiagnosticFactory(
5858
(kind: AnnotationKind, got: number, expected: number) => `'@${kind}' expects ${expected} arguments, but got ${got}.`
5959
);
6060

61-
export const extensionCannotConstruct = createErrorDiagnosticFactory(
62-
"Cannot construct classes with '@extension' or '@metaExtension' annotation."
63-
);
64-
65-
export const extensionCannotExtend = createErrorDiagnosticFactory(
66-
"Cannot extend classes with '@extension' or '@metaExtension' annotation."
67-
);
68-
69-
export const extensionCannotExport = createErrorDiagnosticFactory(
70-
"Cannot export classes with '@extension' or '@metaExtension' annotation."
71-
);
72-
73-
export const extensionInvalidInstanceOf = createErrorDiagnosticFactory(
74-
"Cannot use instanceof on classes with '@extension' or '@metaExtension' annotation."
75-
);
76-
77-
export const extensionAndMetaExtensionConflict = createErrorDiagnosticFactory(
78-
"Cannot use both '@extension' and '@metaExtension' annotations on the same class."
79-
);
80-
81-
export const metaExtensionMissingExtends = createErrorDiagnosticFactory(
82-
"'@metaExtension' annotation requires the extension of the metatable class."
83-
);
84-
8561
export const invalidForRangeCall = createErrorDiagnosticFactory(
8662
(message: string) => `Invalid @forRange call: ${message}.`
8763
);
@@ -182,6 +158,12 @@ export const invalidTableSetExpression = createErrorDiagnosticFactory(
182158
"Table set extension can only be called as a stand-alone statement. It cannot be used as an expression in another statement."
183159
);
184160

161+
export const annotationRemoved = createErrorDiagnosticFactory(
162+
(kind: AnnotationKind) =>
163+
`'@${kind}' has been removed and will no longer have any effect.` +
164+
`See https://typescripttolua.github.io/docs/advanced/compiler-annotations#${kind.toLowerCase()} for more information.`
165+
);
166+
185167
export const annotationDeprecated = createWarningDiagnosticFactory(
186168
(kind: AnnotationKind) =>
187169
`'@${kind}' is deprecated and will be removed in a future update. Please update your code before upgrading to the next release, otherwise your project will no longer compile. ` +

src/transformation/visitors/binary-expression/index.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as ts from "typescript";
22
import * as lua from "../../../LuaAST";
33
import { FunctionVisitor, TransformationContext } from "../../context";
44
import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations";
5-
import { extensionInvalidInstanceOf, luaTableInvalidInstanceOf } from "../../utils/diagnostics";
5+
import { luaTableInvalidInstanceOf } from "../../utils/diagnostics";
66
import { createImmediatelyInvokedFunctionExpression, wrapInToStringForConcat } from "../../utils/lua-ast";
77
import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib";
88
import { isStandardLibraryType, isStringType, typeCanSatisfy } from "../../utils/typescript";
@@ -109,10 +109,6 @@ export const transformBinaryExpression: FunctionVisitor<ts.BinaryExpression> = (
109109
const rhsType = context.checker.getTypeAtLocation(node.right);
110110
const annotations = getTypeAnnotations(rhsType);
111111

112-
if (annotations.has(AnnotationKind.Extension) || annotations.has(AnnotationKind.MetaExtension)) {
113-
context.diagnostics.push(extensionInvalidInstanceOf(node));
114-
}
115-
116112
if (annotations.has(AnnotationKind.LuaTable)) {
117113
context.diagnostics.push(luaTableInvalidInstanceOf(node));
118114
}

src/transformation/visitors/class/index.ts

Lines changed: 58 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,10 @@ import * as lua from "../../../LuaAST";
33
import { getOrUpdate } from "../../../utils";
44
import { FunctionVisitor, TransformationContext } from "../../context";
55
import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations";
6-
import {
7-
annotationDeprecated,
8-
extensionAndMetaExtensionConflict,
9-
extensionCannotExport,
10-
extensionCannotExtend,
11-
luaTableCannotBeExtended,
12-
luaTableMustBeAmbient,
13-
metaExtensionMissingExtends,
14-
} from "../../utils/diagnostics";
6+
import { annotationRemoved, luaTableCannotBeExtended, luaTableMustBeAmbient } from "../../utils/diagnostics";
157
import {
168
createDefaultExportIdentifier,
179
createExportedIdentifier,
18-
getIdentifierExportScope,
1910
hasDefaultExportModifier,
2011
isSymbolExported,
2112
} from "../../utils/export";
@@ -28,7 +19,6 @@ import { createSafeName, isUnsafeName } from "../../utils/safe-names";
2819
import { popScope, pushScope, ScopeType } from "../../utils/scope";
2920
import { isAmbientNode } from "../../utils/typescript";
3021
import { transformIdentifier } from "../identifier";
31-
import { transformPropertyName } from "../literal";
3222
import { createDecoratingExpression, transformDecoratorExpression } from "./decorators";
3323
import { transformAccessorDeclarations } from "./members/accessors";
3424
import { createConstructorName, transformConstructorDeclaration } from "./members/constructor";
@@ -90,25 +80,11 @@ function transformClassLikeDeclaration(
9080

9181
const annotations = getTypeAnnotations(context.checker.getTypeAtLocation(classDeclaration));
9282

93-
// Find out if this class is extension of existing class
94-
const extensionDirective = annotations.get(AnnotationKind.Extension);
95-
const isExtension = extensionDirective !== undefined;
96-
const isMetaExtension = annotations.has(AnnotationKind.MetaExtension);
97-
98-
if (isExtension) {
99-
context.diagnostics.push(annotationDeprecated(classDeclaration, AnnotationKind.Extension));
83+
if (annotations.has(AnnotationKind.Extension)) {
84+
context.diagnostics.push(annotationRemoved(classDeclaration, AnnotationKind.Extension));
10085
}
101-
if (isMetaExtension) {
102-
context.diagnostics.push(annotationDeprecated(classDeclaration, AnnotationKind.MetaExtension));
103-
}
104-
105-
if (isExtension && isMetaExtension) {
106-
context.diagnostics.push(extensionAndMetaExtensionConflict(classDeclaration));
107-
}
108-
109-
if ((isExtension || isMetaExtension) && getIdentifierExportScope(context, className) !== undefined) {
110-
// Cannot export extension classes
111-
context.diagnostics.push(extensionCannotExport(classDeclaration));
86+
if (annotations.has(AnnotationKind.MetaExtension)) {
87+
context.diagnostics.push(annotationRemoved(classDeclaration, AnnotationKind.MetaExtension));
11288
}
11389

11490
// Get type that is extended
@@ -122,14 +98,6 @@ function transformClassLikeDeclaration(
12298
checkForLuaLibType(context, extendedType);
12399
}
124100

125-
if (!(isExtension || isMetaExtension) && extendedType) {
126-
// Non-extensions cannot extend extension classes
127-
const extendsAnnotations = getTypeAnnotations(extendedType);
128-
if (extendsAnnotations.has(AnnotationKind.Extension) || extendsAnnotations.has(AnnotationKind.MetaExtension)) {
129-
context.diagnostics.push(extensionCannotExtend(classDeclaration));
130-
}
131-
}
132-
133101
// You cannot extend LuaTable classes
134102
if (extendedType) {
135103
const annotations = getTypeAnnotations(extendedType);
@@ -150,43 +118,6 @@ function transformClassLikeDeclaration(
150118

151119
const result: lua.Statement[] = [];
152120

153-
// Overwrite the original className with the class we are overriding for extensions
154-
if (isMetaExtension) {
155-
if (extendedType) {
156-
const extendsName = lua.createStringLiteral(extendedType.symbol.name);
157-
className = lua.createIdentifier("__meta__" + extendsName.value);
158-
159-
// local className = debug.getregistry()["extendsName"]
160-
const assignDebugCallIndex = lua.createVariableDeclarationStatement(
161-
className,
162-
lua.createTableIndexExpression(
163-
lua.createCallExpression(
164-
lua.createTableIndexExpression(
165-
lua.createIdentifier("debug"),
166-
lua.createStringLiteral("getregistry")
167-
),
168-
[]
169-
),
170-
extendsName
171-
),
172-
classDeclaration
173-
);
174-
175-
result.push(assignDebugCallIndex);
176-
} else {
177-
context.diagnostics.push(metaExtensionMissingExtends(classDeclaration));
178-
}
179-
}
180-
181-
if (extensionDirective !== undefined) {
182-
const [extensionName] = extensionDirective.args;
183-
if (extensionName) {
184-
className = lua.createIdentifier(extensionName);
185-
} else if (extendedType) {
186-
className = lua.createIdentifier(extendedType.symbol.name);
187-
}
188-
}
189-
190121
let localClassName: lua.Identifier;
191122
if (isUnsafeName(className.text)) {
192123
localClassName = lua.createIdentifier(
@@ -200,82 +131,60 @@ function transformClassLikeDeclaration(
200131
localClassName = className;
201132
}
202133

203-
if (!isExtension && !isMetaExtension) {
204-
result.push(...createClassSetup(context, classDeclaration, className, localClassName, extendedType));
205-
} else {
206-
for (const f of instanceFields) {
207-
const fieldName = transformPropertyName(context, f.name);
208-
209-
const value = f.initializer !== undefined ? context.transformExpression(f.initializer) : undefined;
134+
result.push(...createClassSetup(context, classDeclaration, className, localClassName, extendedType));
210135

211-
// className["fieldName"]
212-
const classField = lua.createTableIndexExpression(lua.cloneIdentifier(className), fieldName);
213-
214-
// className["fieldName"] = value;
215-
const assignClassField = lua.createAssignmentStatement(classField, value);
136+
// Find first constructor with body
137+
const constructor = classDeclaration.members.find(
138+
(n): n is ts.ConstructorDeclaration => ts.isConstructorDeclaration(n) && n.body !== undefined
139+
);
216140

217-
result.push(assignClassField);
218-
}
219-
}
141+
if (constructor) {
142+
// Add constructor plus initialization of instance fields
143+
const constructorResult = transformConstructorDeclaration(
144+
context,
145+
constructor,
146+
localClassName,
147+
instanceFields,
148+
classDeclaration
149+
);
220150

221-
// Find first constructor with body
222-
if (!isExtension && !isMetaExtension) {
223-
const constructor = classDeclaration.members.find(
224-
(n): n is ts.ConstructorDeclaration => ts.isConstructorDeclaration(n) && n.body !== undefined
151+
if (constructorResult) result.push(constructorResult);
152+
} else if (!extendedType) {
153+
// Generate a constructor if none was defined in a base class
154+
const constructorResult = transformConstructorDeclaration(
155+
context,
156+
ts.createConstructor([], [], [], ts.createBlock([], true)),
157+
localClassName,
158+
instanceFields,
159+
classDeclaration
225160
);
226161

227-
if (constructor) {
228-
// Add constructor plus initialization of instance fields
229-
const constructorResult = transformConstructorDeclaration(
230-
context,
231-
constructor,
232-
localClassName,
233-
instanceFields,
234-
classDeclaration
235-
);
236-
237-
if (constructorResult) result.push(constructorResult);
238-
} else if (!extendedType) {
239-
// Generate a constructor if none was defined in a base class
240-
const constructorResult = transformConstructorDeclaration(
241-
context,
242-
ts.createConstructor([], [], [], ts.createBlock([], true)),
243-
localClassName,
244-
instanceFields,
245-
classDeclaration
246-
);
247-
248-
if (constructorResult) result.push(constructorResult);
249-
} else if (instanceFields.length > 0) {
250-
// Generate a constructor if none was defined in a class with instance fields that need initialization
251-
// localClassName.prototype.____constructor = function(self, ...)
252-
// baseClassName.prototype.____constructor(self, ...)
253-
// ...
254-
const constructorBody = transformClassInstanceFields(context, instanceFields);
255-
const superCall = lua.createExpressionStatement(
256-
lua.createCallExpression(
257-
lua.createTableIndexExpression(
258-
context.transformExpression(ts.createSuper()),
259-
lua.createStringLiteral("____constructor")
260-
),
261-
[createSelfIdentifier(), lua.createDotsLiteral()]
262-
)
263-
);
264-
constructorBody.unshift(superCall);
265-
const constructorFunction = lua.createFunctionExpression(
266-
lua.createBlock(constructorBody),
267-
[createSelfIdentifier()],
268-
lua.createDotsLiteral(),
269-
lua.FunctionExpressionFlags.Declaration
270-
);
271-
result.push(
272-
lua.createAssignmentStatement(
273-
createConstructorName(localClassName),
274-
constructorFunction,
275-
classDeclaration
276-
)
277-
);
278-
}
162+
if (constructorResult) result.push(constructorResult);
163+
} else if (instanceFields.length > 0) {
164+
// Generate a constructor if none was defined in a class with instance fields that need initialization
165+
// localClassName.prototype.____constructor = function(self, ...)
166+
// baseClassName.prototype.____constructor(self, ...)
167+
// ...
168+
const constructorBody = transformClassInstanceFields(context, instanceFields);
169+
const superCall = lua.createExpressionStatement(
170+
lua.createCallExpression(
171+
lua.createTableIndexExpression(
172+
context.transformExpression(ts.createSuper()),
173+
lua.createStringLiteral("____constructor")
174+
),
175+
[createSelfIdentifier(), lua.createDotsLiteral()]
176+
)
177+
);
178+
constructorBody.unshift(superCall);
179+
const constructorFunction = lua.createFunctionExpression(
180+
lua.createBlock(constructorBody),
181+
[createSelfIdentifier()],
182+
lua.createDotsLiteral(),
183+
lua.FunctionExpressionFlags.Declaration
184+
);
185+
result.push(
186+
lua.createAssignmentStatement(createConstructorName(localClassName), constructorFunction, classDeclaration)
187+
);
279188
}
280189

281190
// Transform accessors
@@ -290,26 +199,25 @@ function transformClassLikeDeclaration(
290199
}
291200
}
292201

293-
const noPrototype = isExtension || isMetaExtension;
294202
const decorationStatements: lua.Statement[] = [];
295203

296204
for (const member of classDeclaration.members) {
297205
if (ts.isAccessor(member)) {
298-
const expression = createPropertyDecoratingExpression(context, member, localClassName, noPrototype);
206+
const expression = createPropertyDecoratingExpression(context, member, localClassName);
299207
if (expression) decorationStatements.push(lua.createExpressionStatement(expression));
300208
} else if (ts.isMethodDeclaration(member)) {
301-
const statement = transformMethodDeclaration(context, member, localClassName, noPrototype);
209+
const statement = transformMethodDeclaration(context, member, localClassName);
302210
if (statement) result.push(statement);
303211
if (member.body) {
304-
const statement = createMethodDecoratingExpression(context, member, localClassName, noPrototype);
212+
const statement = createMethodDecoratingExpression(context, member, localClassName);
305213
if (statement) decorationStatements.push(statement);
306214
}
307215
} else if (ts.isPropertyDeclaration(member)) {
308216
if (isStaticNode(member)) {
309217
const statement = transformStaticPropertyDeclaration(context, member, localClassName);
310218
if (statement) decorationStatements.push(statement);
311219
}
312-
const expression = createPropertyDecoratingExpression(context, member, localClassName, noPrototype);
220+
const expression = createPropertyDecoratingExpression(context, member, localClassName);
313221
if (expression) decorationStatements.push(lua.createExpressionStatement(expression));
314222
}
315223
}

src/transformation/visitors/class/members/fields.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ import { transformMemberExpressionOwnerName } from "./method";
99
export function createPropertyDecoratingExpression(
1010
context: TransformationContext,
1111
node: ts.PropertyDeclaration | ts.AccessorDeclaration,
12-
className: lua.Identifier,
13-
noPrototype: boolean
12+
className: lua.Identifier
1413
): lua.Expression | undefined {
1514
if (!node.decorators) return;
1615
const propertyName = transformPropertyName(context, node.name);
17-
const propertyOwnerTable = transformMemberExpressionOwnerName(node, className, noPrototype);
16+
const propertyOwnerTable = transformMemberExpressionOwnerName(node, className);
1817
return createDecoratingExpression(
1918
context,
2019
node.kind,

0 commit comments

Comments
 (0)