Skip to content

Commit

Permalink
Merge branch 'master' into typescript-5.3
Browse files Browse the repository at this point in the history
  • Loading branch information
osyrisrblx committed Feb 14, 2024
2 parents 0cfdccc + b6a50d1 commit 47f7725
Show file tree
Hide file tree
Showing 44 changed files with 542 additions and 968 deletions.
2 changes: 1 addition & 1 deletion src/Project/classes/VirtualProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export class VirtualProject {
this.program = ts.createProgram(rootNames, this.compilerOptions, this.compilerHost, this.program);
this.typeChecker = this.program.getTypeChecker();

const services = createTransformServices(this.program, this.typeChecker, this.data);
const services = createTransformServices(this.typeChecker);
const pathTranslator = new PathTranslator(ROOT_DIR, OUT_DIR, undefined, false);

const sourceFile = this.program.getSourceFile(PLAYGROUND_PATH);
Expand Down
2 changes: 1 addition & 1 deletion src/Project/functions/compileFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export function compileFiles(
if (DiagnosticService.hasErrors()) return { emitSkipped: true, diagnostics: DiagnosticService.flush() };

const typeChecker = proxyProgram.getTypeChecker();
const services = createTransformServices(proxyProgram, typeChecker, data);
const services = createTransformServices(typeChecker);

for (let i = 0; i < sourceFiles.length; i++) {
const sourceFile = proxyProgram.getSourceFile(sourceFiles[i].fileName);
Expand Down
14 changes: 2 additions & 12 deletions src/Shared/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,18 +197,8 @@ export const errors = {
suggestion("Move the file you want to import to a shared location."),
),

// roact jsx
invalidJsxFactory: error("compilerOptions.jsxFactory must be `Roact.createElement`!"),
invalidJsxFragmentFactory: error("compilerOptions.jsxFragmentFactory must be `Roact.createFragment`!"),
noRoactInheritance: error(
"Composition is preferred over inheritance with Roact components.",
"More info: https://reactjs.org/docs/composition-vs-inheritance.html",
),
noSuperPropertyCallRoactComponent: error("`super` is not supported inside Roact components!"),
missingSuperConstructorRoactComponent: error(
"`super(props)` must be the first statement of the constructor in a Roact component!",
),
noJsxText: error("JSX text is not supported!"),
// jsx
noPrecedingJsxSpreadElement: error("JSX spread expression must come last in children!"),

// semantic
expectedMethodGotFunction: error("Attempted to assign non-method where method was expected."),
Expand Down
2 changes: 1 addition & 1 deletion src/Shared/util/findLastIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @param array The array to search.
* @param callback A function to execute on each value in the array until the function returns `true`, indicating that the satisfying element was found.
*/
export function findLastIndex<T>(array: Array<T>, callback: (value: T) => boolean) {
export function findLastIndex<T>(array: ReadonlyArray<T>, callback: (value: T) => boolean) {
for (let i = array.length - 1; i >= 0; i--) {
if (callback(array[i])) {
return i;
Expand Down
92 changes: 0 additions & 92 deletions src/TSTransformer/classes/RoactSymbolManager.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/TSTransformer/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from "TSTransformer/classes/MacroManager";
export * from "TSTransformer/classes/MultiTransformState";
export * from "TSTransformer/classes/RoactSymbolManager";
export * from "TSTransformer/classes/TransformState";
export { transformSourceFile } from "TSTransformer/nodes/transformSourceFile";
2 changes: 1 addition & 1 deletion src/TSTransformer/macros/propertyCallMacros.ts
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,7 @@ const SET_MAP_SHARED_METHODS: MacroList<PropertyCallMacro> = {
valueExistedId = state.pushToVar(
luau.create(luau.SyntaxKind.BinaryExpression, {
left: luau.create(luau.SyntaxKind.ComputedIndexExpression, {
expression: convertToIndexableExpression(expression),
expression,
index: arg,
}),
operator: "~=",
Expand Down
8 changes: 3 additions & 5 deletions src/TSTransformer/nodes/class/transformClassConstructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { transformIdentifierDefined } from "TSTransformer/nodes/expressions/tran
import { transformParameters } from "TSTransformer/nodes/transformParameters";
import { transformPropertyName } from "TSTransformer/nodes/transformPropertyName";
import { transformStatementList } from "TSTransformer/nodes/transformStatementList";
import { extendsRoactComponent } from "TSTransformer/util/extendsRoactComponent";
import { getExtendsNode } from "TSTransformer/util/getExtendsNode";
import { getStatements } from "TSTransformer/util/getStatements";
import ts from "typescript";
Expand All @@ -22,8 +21,7 @@ export function transformClassConstructor(

let bodyStatements = originNode ? getStatements(originNode.body) : [];

const isRoact = extendsRoactComponent(state, node);
let removeFirstSuper = isRoact;
let removeFirstSuper = false;

let parameters = luau.list.make<luau.AnyIdentifier>();
let hasDotDotDot = false;
Expand All @@ -36,7 +34,7 @@ export function transformClassConstructor(
luau.list.pushList(statements, paramStatements);
parameters = constructorParams;
hasDotDotDot = constructorHasDotDotDot;
} else if (!isRoact && getExtendsNode(node)) {
} else if (getExtendsNode(node)) {
// if extends + no constructor:
// - add ... to params
// - add super.constructor(self, ...)
Expand Down Expand Up @@ -128,7 +126,7 @@ export function transformClassConstructor(
return luau.list.make<luau.Statement>(
luau.create(luau.SyntaxKind.MethodDeclaration, {
expression: name,
name: isRoact ? "init" : "constructor",
name: "constructor",
statements,
parameters,
hasDotDotDot,
Expand Down
74 changes: 3 additions & 71 deletions src/TSTransformer/nodes/class/transformClassLikeDeclaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import { transformExpression } from "TSTransformer/nodes/expressions/transformEx
import { transformIdentifierDefined } from "TSTransformer/nodes/expressions/transformIdentifier";
import { transformBlock } from "TSTransformer/nodes/statements/transformBlock";
import { transformMethodDeclaration } from "TSTransformer/nodes/transformMethodDeclaration";
import { convertToIndexableExpression } from "TSTransformer/util/convertToIndexableExpression";
import { extendsRoactComponent } from "TSTransformer/util/extendsRoactComponent";
import { getExtendsNode } from "TSTransformer/util/getExtendsNode";
import { getKindName } from "TSTransformer/util/getKindName";
import { getOriginalSymbolOfNode } from "TSTransformer/util/getOriginalSymbolOfNode";
Expand Down Expand Up @@ -40,60 +38,6 @@ function createNameFunction(name: string) {
});
}

function createRoactBoilerplate(
state: TransformState,
node: ts.ClassLikeDeclaration,
className: luau.Identifier | luau.TemporaryIdentifier,
isClassExpression: boolean,
) {
const extendsNode = getExtendsNode(node);
assert(extendsNode);

const statements = luau.list.make<luau.Statement>();

const [extendsExp, extendsExpPrereqs] = state.capture(() => transformExpression(state, extendsNode.expression));
luau.list.pushList(statements, extendsExpPrereqs);

const classNameStr = luau.isIdentifier(className) ? className.name : "Anonymous";

const right = luau.create(luau.SyntaxKind.MethodCallExpression, {
expression: convertToIndexableExpression(extendsExp),
name: "extend",
args: luau.list.make(luau.string(classNameStr)),
});

if (isClassExpression && node.name) {
luau.list.push(
statements,
luau.create(luau.SyntaxKind.VariableDeclaration, {
left: transformIdentifierDefined(state, node.name),
right,
}),
);
} else {
luau.list.push(
statements,
luau.create(luau.SyntaxKind.Assignment, {
left: className,
operator: "=",
right,
}),
);
}

return statements;
}

function getExtendsDeclaration(state: TransformState, extendsExp: ts.Expression) {
if (ts.isClassLike(extendsExp)) {
return extendsExp;
}
const symbol = state.typeChecker.getSymbolAtLocation(extendsExp);
if (symbol && symbol.valueDeclaration && ts.isClassLike(symbol.valueDeclaration)) {
return symbol.valueDeclaration;
}
}

function createBoilerplate(
state: TransformState,
node: ts.ClassLikeDeclaration,
Expand Down Expand Up @@ -131,7 +75,7 @@ function createBoilerplate(
luau.create(luau.SyntaxKind.Assignment, {
left: className,
operator: "=",
right: luau.mixedTable(),
right: luau.map(),
}),
);
} else {
Expand All @@ -145,11 +89,6 @@ function createBoilerplate(
);

if (extendsNode) {
const extendsDec = getExtendsDeclaration(state, extendsNode.expression);
if (extendsDec && extendsRoactComponent(state, extendsDec)) {
DiagnosticService.addDiagnostic(errors.noRoactInheritance(node));
}

const [extendsExp, extendsExpPrereqs] = state.capture(() =>
transformExpression(state, extendsNode.expression),
);
Expand Down Expand Up @@ -332,24 +271,17 @@ export function transformClassLikeDeclaration(state: TransformState, node: ts.Cl
DiagnosticService.addDiagnostic(errors.noMacroExtends(node));
}

const isRoact = extendsRoactComponent(state, node);

// OOP boilerplate + class functions
const statementsInner = luau.list.make<luau.Statement>();
if (isRoact) {
luau.list.pushList(statementsInner, createRoactBoilerplate(state, node, internalName, isClassExpression));
} else {
luau.list.pushList(statementsInner, createBoilerplate(state, node, internalName, isClassExpression));
}
luau.list.pushList(statementsInner, createBoilerplate(state, node, internalName, isClassExpression));

luau.list.pushList(statementsInner, transformClassConstructor(state, node, internalName, getConstructor(node)));

for (const member of node.members) {
if (
(ts.isPropertyDeclaration(member) || ts.isMethodDeclaration(member)) &&
(ts.isIdentifier(member.name) || ts.isStringLiteral(member.name)) &&
(luau.isReservedClassField(member.name.text) ||
(isRoact && luau.isReservedRoactClassField(member.name.text)))
luau.isReservedClassField(member.name.text)
) {
DiagnosticService.addDiagnostic(errors.noReservedClassFields(member.name));
}
Expand Down
10 changes: 0 additions & 10 deletions src/TSTransformer/nodes/expressions/transformCallExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { addOneIfArrayType } from "TSTransformer/util/addOneIfArrayType";
import { convertToIndexableExpression } from "TSTransformer/util/convertToIndexableExpression";
import { ensureTransformOrder } from "TSTransformer/util/ensureTransformOrder";
import { expressionMightMutate } from "TSTransformer/util/expressionMightMutate";
import { isInsideRoactComponent } from "TSTransformer/util/isInsideRoactComponent";
import { isMethod } from "TSTransformer/util/isMethod";
import { isSymbolFromRobloxTypes } from "TSTransformer/util/isSymbolFromRobloxTypes";
import { getFirstDefinedSymbol, isPossiblyType, isUndefinedType } from "TSTransformer/util/types";
Expand Down Expand Up @@ -122,9 +121,6 @@ export function transformCallExpressionInner(
validateNotAnyType(state, node.expression);

if (ts.isSuperCall(node)) {
if (isInsideRoactComponent(state, node)) {
DiagnosticService.addDiagnostic(errors.missingSuperConstructorRoactComponent(node));
}
return luau.call(luau.property(convertToIndexableExpression(expression), "constructor"), [
luau.globals.self,
...ensureTransformOrder(state, node.arguments),
Expand Down Expand Up @@ -167,9 +163,6 @@ export function transformPropertyCallExpressionInner(
validateNotAnyType(state, node.expression);

if (ts.isSuperProperty(expression)) {
if (isInsideRoactComponent(state, node)) {
DiagnosticService.addDiagnostic(errors.noSuperPropertyCallRoactComponent(node));
}
return luau.call(luau.property(convertToIndexableExpression(baseExpression), expression.name.text), [
luau.globals.self,
...ensureTransformOrder(state, node.arguments),
Expand Down Expand Up @@ -232,9 +225,6 @@ export function transformElementCallExpressionInner(
validateNotAnyType(state, node.expression);

if (ts.isSuperProperty(expression)) {
if (isInsideRoactComponent(state, node)) {
DiagnosticService.addDiagnostic(errors.noSuperPropertyCallRoactComponent(node));
}
return luau.call(
luau.create(luau.SyntaxKind.ComputedIndexExpression, {
expression: convertToIndexableExpression(baseExpression),
Expand Down
2 changes: 2 additions & 0 deletions src/TSTransformer/nodes/expressions/transformExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { transformElementAccessExpression } from "TSTransformer/nodes/expression
import { transformFunctionExpression } from "TSTransformer/nodes/expressions/transformFunctionExpression";
import { transformIdentifier } from "TSTransformer/nodes/expressions/transformIdentifier";
import { transformJsxElement } from "TSTransformer/nodes/expressions/transformJsxElement";
import { transformJsxExpression } from "TSTransformer/nodes/expressions/transformJsxExpression";
import { transformJsxFragment } from "TSTransformer/nodes/expressions/transformJsxFragment";
import { transformJsxSelfClosingElement } from "TSTransformer/nodes/expressions/transformJsxSelfClosingElement";
import { transformNewExpression } from "TSTransformer/nodes/expressions/transformNewExpression";
Expand Down Expand Up @@ -77,6 +78,7 @@ const TRANSFORMER_BY_KIND = new Map<ts.SyntaxKind, ExpressionTransformer>([
[ts.SyntaxKind.FunctionExpression, transformFunctionExpression],
[ts.SyntaxKind.Identifier, transformIdentifier],
[ts.SyntaxKind.JsxElement, transformJsxElement],
[ts.SyntaxKind.JsxExpression, transformJsxExpression],
[ts.SyntaxKind.JsxFragment, transformJsxFragment],
[ts.SyntaxKind.JsxSelfClosingElement, transformJsxSelfClosingElement],
[ts.SyntaxKind.NewExpression, transformNewExpression],
Expand Down
7 changes: 7 additions & 0 deletions src/TSTransformer/nodes/expressions/transformIdentifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ function checkIdentifierHoist(state: TransformState, node: ts.Identifier, symbol
}

export function transformIdentifier(state: TransformState, node: ts.Identifier) {
// synthetic nodes don't have parents or symbols, so skip all the symbol-related logic
// JSX EntityName functions like `getJsxFactoryEntity()` will return synthetic nodes
// and transformEntityName will eventually end up here
if (!node.parent || ts.positionIsSynthesized(node.pos)) {
return luau.create(luau.SyntaxKind.Identifier, { name: node.text });
}

const symbol = ts.isShorthandPropertyAssignment(node.parent)
? state.typeChecker.getShorthandAssignmentValueSymbol(node.parent)
: state.typeChecker.getSymbolAtLocation(node);
Expand Down
15 changes: 15 additions & 0 deletions src/TSTransformer/nodes/expressions/transformJsxExpression.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import luau from "@roblox-ts/luau-ast";
import { TransformState } from "TSTransformer";
import { transformExpression } from "TSTransformer/nodes/expressions/transformExpression";
import ts from "typescript";

export function transformJsxExpression(state: TransformState, node: ts.JsxExpression) {
if (node.expression) {
const expression = transformExpression(state, node.expression);
if (node.dotDotDotToken) {
return luau.call(luau.globals.unpack, [expression]);
}
return expression;
}
return luau.none();
}

0 comments on commit 47f7725

Please sign in to comment.