Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions src/lualib/declarations/luatable.d.ts

This file was deleted.

30 changes: 0 additions & 30 deletions src/transformation/utils/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@ export const annotationInvalidArgumentCount = createErrorDiagnosticFactory(
(kind: AnnotationKind, got: number, expected: number) => `'@${kind}' expects ${expected} arguments, but got ${got}.`
);

export const invalidForRangeCall = createErrorDiagnosticFactory(
(message: string) => `Invalid @forRange call: ${message}.`
);

export const invalidRangeUse = createErrorDiagnosticFactory("$range can only be used in a for...of loop.");

export const invalidVarargUse = createErrorDiagnosticFactory(
Expand All @@ -72,32 +68,6 @@ export const invalidRangeControlVariable = createErrorDiagnosticFactory(
"For loop using $range must declare a single control variable."
);

export const luaTableMustBeAmbient = createErrorDiagnosticFactory(
"Classes with the '@luaTable' annotation must be ambient."
);

export const luaTableCannotBeExtended = createErrorDiagnosticFactory(
"Cannot extend classes with the '@luaTable' annotation."
);

export const luaTableInvalidInstanceOf = createErrorDiagnosticFactory(
"The instanceof operator cannot be used with a '@luaTable' class."
);

export const luaTableCannotBeAccessedDynamically = createErrorDiagnosticFactory(
"@luaTable cannot be accessed dynamically."
);

export const luaTableForbiddenUsage = createErrorDiagnosticFactory(
(description: string) => `Invalid @luaTable usage: ${description}.`
);

export const luaIteratorForbiddenUsage = createErrorDiagnosticFactory(
"Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. " +
"You must use a destructuring statement to catch results from a lua iterator with " +
"the '@tupleReturn' annotation."
);

export const invalidMultiIterableWithoutDestructuring = createErrorDiagnosticFactory(
"LuaIterable with a LuaMultiReturn return value type must be destructured."
);
Expand Down
52 changes: 23 additions & 29 deletions src/transformation/visitors/access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import * as lua from "../../LuaAST";
import { transformBuiltinPropertyAccessExpression } from "../builtins";
import { FunctionVisitor, TransformationContext } from "../context";
import { AnnotationKind, getTypeAnnotations } from "../utils/annotations";
import { invalidMultiReturnAccess, optionalChainingNotSupported } from "../utils/diagnostics";
import { annotationRemoved, invalidMultiReturnAccess, optionalChainingNotSupported } from "../utils/diagnostics";
import { addToNumericExpression } from "../utils/lua-ast";
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
import { isArrayType, isNumberType, isStringType } from "../utils/typescript";
import { tryGetConstEnumValue } from "./enum";
import { returnsMultiType } from "./language-extensions/multi";
import { transformLuaTablePropertyAccessExpression, validateLuaTableElementAccessExpression } from "./lua-table";

export function transformElementAccessArgument(
context: TransformationContext,
Expand All @@ -27,8 +26,6 @@ export function transformElementAccessArgument(
}

export const transformElementAccessExpression: FunctionVisitor<ts.ElementAccessExpression> = (node, context) => {
validateLuaTableElementAccessExpression(context, node);

const constEnumValue = tryGetConstEnumValue(context, node);
if (constEnumValue) {
return constEnumValue;
Expand Down Expand Up @@ -59,53 +56,50 @@ export const transformElementAccessExpression: FunctionVisitor<ts.ElementAccessE
return lua.createTableIndexExpression(table, accessExpression, node);
};

export const transformPropertyAccessExpression: FunctionVisitor<ts.PropertyAccessExpression> = (
expression,
context
) => {
if (ts.isOptionalChain(expression)) {
context.diagnostics.push(optionalChainingNotSupported(expression));
export const transformPropertyAccessExpression: FunctionVisitor<ts.PropertyAccessExpression> = (node, context) => {
const property = node.name.text;
const type = context.checker.getTypeAtLocation(node.expression);

const annotations = getTypeAnnotations(type);

if (annotations.has(AnnotationKind.LuaTable)) {
context.diagnostics.push(annotationRemoved(node, AnnotationKind.LuaTable));
}

const constEnumValue = tryGetConstEnumValue(context, expression);
if (constEnumValue) {
return constEnumValue;
if (ts.isOptionalChain(node)) {
context.diagnostics.push(optionalChainingNotSupported(node));
}

const luaTableResult = transformLuaTablePropertyAccessExpression(context, expression);
if (luaTableResult) {
return luaTableResult;
const constEnumValue = tryGetConstEnumValue(context, node);
if (constEnumValue) {
return constEnumValue;
}

const builtinResult = transformBuiltinPropertyAccessExpression(context, expression);
const builtinResult = transformBuiltinPropertyAccessExpression(context, node);
if (builtinResult) {
return builtinResult;
}

if (ts.isCallExpression(expression.expression) && returnsMultiType(context, expression.expression)) {
context.diagnostics.push(invalidMultiReturnAccess(expression));
if (ts.isCallExpression(node.expression) && returnsMultiType(context, node.expression)) {
context.diagnostics.push(invalidMultiReturnAccess(node));
}

const property = expression.name.text;
const type = context.checker.getTypeAtLocation(expression.expression);

const annotations = getTypeAnnotations(type);
// Do not output path for member only enums
if (annotations.has(AnnotationKind.CompileMembersOnly)) {
if (ts.isPropertyAccessExpression(expression.expression)) {
if (ts.isPropertyAccessExpression(node.expression)) {
// in case of ...x.enum.y transform to ...x.y
return lua.createTableIndexExpression(
context.transformExpression(expression.expression.expression),
context.transformExpression(node.expression.expression),
lua.createStringLiteral(property),
expression
node
);
} else {
return lua.createIdentifier(property, expression);
return lua.createIdentifier(property, node);
}
}

const callPath = context.transformExpression(expression.expression);
return lua.createTableIndexExpression(callPath, lua.createStringLiteral(property), expression);
const callPath = context.transformExpression(node.expression);
return lua.createTableIndexExpression(callPath, lua.createStringLiteral(property), node);
};

export const transformQualifiedName: FunctionVisitor<ts.QualifiedName> = (node, context) => {
Expand Down
8 changes: 1 addition & 7 deletions src/transformation/visitors/binary-expression/assignments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { createUnpackCall, wrapInTable } from "../../utils/lua-ast";
import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib";
import { isArrayType, isDestructuringAssignment } from "../../utils/typescript";
import { transformElementAccessArgument } from "../access";
import { transformLuaTablePropertyAccessInAssignment } from "../lua-table";
import { isArrayLength, transformDestructuringAssignment } from "./destructuring-assignments";
import { isMultiReturnCall } from "../language-extensions/multi";
import { popScope, pushScope, ScopeType } from "../../utils/scope";
Expand All @@ -23,9 +22,7 @@ export function transformAssignmentLeftHandSideExpression(
node: ts.Expression
): lua.AssignmentLeftHandSideExpression {
const symbol = context.checker.getSymbolAtLocation(node);
const left = ts.isPropertyAccessExpression(node)
? transformLuaTablePropertyAccessInAssignment(context, node) ?? context.transformExpression(node)
: context.transformExpression(node);
const left = context.transformExpression(node);

return lua.isIdentifier(left) && symbol && isSymbolExported(context, symbol)
? createExportedIdentifier(context, left)
Expand Down Expand Up @@ -140,9 +137,6 @@ export function transformAssignmentExpression(
const objExpression = context.transformExpression(expression.left.expression);
let indexExpression: lua.Expression;
if (ts.isPropertyAccessExpression(expression.left)) {
// Called only for validation
transformLuaTablePropertyAccessInAssignment(context, expression.left);

// Property access
indexExpression = lua.createStringLiteral(expression.left.name.text);
} else {
Expand Down
7 changes: 0 additions & 7 deletions src/transformation/visitors/binary-expression/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import * as ts from "typescript";
import * as lua from "../../../LuaAST";
import { FunctionVisitor, TransformationContext } from "../../context";
import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations";
import { luaTableInvalidInstanceOf } from "../../utils/diagnostics";
import { wrapInToStringForConcat } from "../../utils/lua-ast";
import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib";
import { isStandardLibraryType, isStringType, typeCanSatisfy } from "../../utils/typescript";
Expand Down Expand Up @@ -108,11 +106,6 @@ export const transformBinaryExpression: FunctionVisitor<ts.BinaryExpression> = (
const lhs = context.transformExpression(node.left);
const rhs = context.transformExpression(node.right);
const rhsType = context.checker.getTypeAtLocation(node.right);
const annotations = getTypeAnnotations(rhsType);

if (annotations.has(AnnotationKind.LuaTable)) {
context.diagnostics.push(luaTableInvalidInstanceOf(node));
}

if (isStandardLibraryType(context, rhsType, "ObjectConstructor")) {
return transformLuaLibFunction(context, LuaLibFeature.InstanceOfObject, node, lhs);
Expand Down
16 changes: 8 additions & 8 deletions src/transformation/visitors/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ import * as ts from "typescript";
import * as lua from "../../LuaAST";
import { transformBuiltinCallExpression } from "../builtins";
import { FunctionVisitor, TransformationContext } from "../context";
import { isInTupleReturnFunction, isTupleReturnCall } from "../utils/annotations";
import { AnnotationKind, getTypeAnnotations, isInTupleReturnFunction, isTupleReturnCall } from "../utils/annotations";
import { validateAssignment } from "../utils/assignment-validation";
import { ContextType, getDeclarationContextType } from "../utils/function-context";
import { createUnpackCall, wrapInTable } from "../utils/lua-ast";
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
import { isValidLuaIdentifier } from "../utils/safe-names";
import { isExpressionWithEvaluationEffect, isInDestructingAssignment } from "../utils/typescript";
import { transformElementAccessArgument } from "./access";
import { transformLuaTableCallExpression } from "./lua-table";
import { shouldMultiReturnCallBeWrapped } from "./language-extensions/multi";
import { isOperatorMapping, transformOperatorMappingExpression } from "./language-extensions/operators";
import {
Expand All @@ -23,7 +22,7 @@ import {
transformTableHasExpression,
transformTableSetExpression,
} from "./language-extensions/table";
import { invalidTableDeleteExpression, invalidTableSetExpression } from "../utils/diagnostics";
import { annotationRemoved, invalidTableDeleteExpression, invalidTableSetExpression } from "../utils/diagnostics";
import {
ImmediatelyInvokedFunctionParameters,
transformToImmediatelyInvokedFunctionExpression,
Expand Down Expand Up @@ -223,11 +222,6 @@ function transformElementCall(context: TransformationContext, node: ts.CallExpre
}

export const transformCallExpression: FunctionVisitor<ts.CallExpression> = (node, context) => {
const luaTableResult = transformLuaTableCallExpression(context, node);
if (luaTableResult) {
return luaTableResult;
}

const isTupleReturn = isTupleReturnCall(context, node);
const isTupleReturnForward =
node.parent && ts.isReturnStatement(node.parent) && isInTupleReturnFunction(context, node);
Expand Down Expand Up @@ -273,6 +267,12 @@ export const transformCallExpression: FunctionVisitor<ts.CallExpression> = (node
}

if (ts.isPropertyAccessExpression(node.expression)) {
const ownerType = context.checker.getTypeAtLocation(node.expression.expression);
const annotations = getTypeAnnotations(ownerType);
if (annotations.has(AnnotationKind.LuaTable)) {
context.diagnostics.push(annotationRemoved(node, AnnotationKind.LuaTable));
}

const result = transformPropertyCall(context, node as PropertyCallExpression);
return wrapResult ? wrapInTable(result) : result;
}
Expand Down
15 changes: 1 addition & 14 deletions src/transformation/visitors/class/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as lua from "../../../LuaAST";
import { getOrUpdate } from "../../../utils";
import { FunctionVisitor, TransformationContext } from "../../context";
import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations";
import { annotationRemoved, luaTableCannotBeExtended, luaTableMustBeAmbient } from "../../utils/diagnostics";
import { annotationRemoved } from "../../utils/diagnostics";
import {
createDefaultExportIdentifier,
createExportedIdentifier,
Expand All @@ -13,7 +13,6 @@ import {
import { createSelfIdentifier, unwrapVisitorResult } from "../../utils/lua-ast";
import { createSafeName, isUnsafeName } from "../../utils/safe-names";
import { transformToImmediatelyInvokedFunctionExpression } from "../../utils/transform";
import { isAmbientNode } from "../../utils/typescript";
import { transformIdentifier } from "../identifier";
import { createDecoratingExpression, transformDecoratorExpression } from "./decorators";
import { transformAccessorDeclarations } from "./members/accessors";
Expand Down Expand Up @@ -97,18 +96,6 @@ function transformClassLikeDeclaration(
checkForLuaLibType(context, extendedType);
}

// You cannot extend LuaTable classes
if (extendedType) {
const annotations = getTypeAnnotations(extendedType);
if (annotations.has(AnnotationKind.LuaTable)) {
context.diagnostics.push(luaTableCannotBeExtended(extendedTypeNode!));
}
}

if (annotations.has(AnnotationKind.LuaTable) && !isAmbientNode(classDeclaration)) {
context.diagnostics.push(luaTableMustBeAmbient(classDeclaration));
}

// Get all properties with value
const properties = classDeclaration.members.filter(ts.isPropertyDeclaration).filter(member => member.initializer);

Expand Down
16 changes: 7 additions & 9 deletions src/transformation/visitors/class/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import * as ts from "typescript";
import * as lua from "../../../LuaAST";
import { FunctionVisitor, TransformationContext } from "../../context";
import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations";
import { annotationInvalidArgumentCount } from "../../utils/diagnostics";
import { annotationInvalidArgumentCount, annotationRemoved } from "../../utils/diagnostics";
import { importLuaLibFeature, LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib";
import { transformArguments } from "../call";
import { isTableNewCall } from "../language-extensions/table";
import { transformLuaTableNewExpression } from "../lua-table";

const builtinErrorTypeNames = new Set([
"Error",
Expand Down Expand Up @@ -49,9 +48,12 @@ export function checkForLuaLibType(context: TransformationContext, type: ts.Type
}

export const transformNewExpression: FunctionVisitor<ts.NewExpression> = (node, context) => {
const luaTableResult = transformLuaTableNewExpression(context, node);
if (luaTableResult) {
return luaTableResult;
const type = context.checker.getTypeAtLocation(node);

const annotations = getTypeAnnotations(type);

if (annotations.has(AnnotationKind.LuaTable)) {
context.diagnostics.push(annotationRemoved(node, AnnotationKind.LuaTable));
}

if (isTableNewCall(context, node)) {
Expand All @@ -64,12 +66,8 @@ export const transformNewExpression: FunctionVisitor<ts.NewExpression> = (node,
? transformArguments(context, node.arguments, signature)
: [lua.createBooleanLiteral(true)];

const type = context.checker.getTypeAtLocation(node);

checkForLuaLibType(context, type);

const annotations = getTypeAnnotations(type);

const customConstructorAnnotation = annotations.get(AnnotationKind.CustomConstructor);
if (customConstructorAnnotation) {
if (customConstructorAnnotation.args.length === 1) {
Expand Down
15 changes: 5 additions & 10 deletions src/transformation/visitors/expression-statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,17 @@ import {
transformTableDeleteExpression,
transformTableSetExpression,
} from "./language-extensions/table";
import { transformLuaTableExpressionStatement } from "./lua-table";
import { transformUnaryExpressionStatement } from "./unary-expression";

export const transformExpressionStatement: FunctionVisitor<ts.ExpressionStatement> = (node, context) => {
const luaTableResult = transformLuaTableExpressionStatement(context, node);
if (luaTableResult) {
return luaTableResult;
}
const expression = node.expression;

if (ts.isCallExpression(node.expression) && isTableDeleteCall(context, node.expression)) {
return transformTableDeleteExpression(context, node.expression);
if (ts.isCallExpression(expression) && isTableDeleteCall(context, expression)) {
return transformTableDeleteExpression(context, expression);
}

if (ts.isCallExpression(node.expression) && isTableSetCall(context, node.expression)) {
return transformTableSetExpression(context, node.expression);
if (ts.isCallExpression(expression) && isTableSetCall(context, expression)) {
return transformTableSetExpression(context, expression);
}

const unaryExpressionResult = transformUnaryExpressionStatement(context, node);
Expand All @@ -35,7 +31,6 @@ export const transformExpressionStatement: FunctionVisitor<ts.ExpressionStatemen
return binaryExpressionResult;
}

const expression = ts.isExpressionStatement(node) ? node.expression : node;
const result = context.transformExpression(expression);
return lua.isCallExpression(result) || lua.isMethodCallExpression(result)
? lua.createExpressionStatement(result)
Expand Down
Loading