-
Notifications
You must be signed in to change notification settings - Fork 57
Fix class transpile issue with child class constructor not inherriting parent params #1390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
11626af
e94e807
9f829f2
6f1cb12
60ccc63
cee7507
780363a
9bd7f77
ce8c570
c71189b
c3cfb4d
667749a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| /* eslint-disable no-bitwise */ | ||
| import type { Token, Identifier } from '../lexer/Token'; | ||
| import { CompoundAssignmentOperators, TokenKind } from '../lexer/TokenKind'; | ||
| import type { BinaryExpression, NamespacedVariableNameExpression, FunctionExpression, FunctionParameterExpression, LiteralExpression } from './Expression'; | ||
| import { type BinaryExpression, type NamespacedVariableNameExpression, FunctionExpression, type FunctionParameterExpression, type LiteralExpression } from './Expression'; | ||
| import { CallExpression, VariableExpression } from './Expression'; | ||
| import { util } from '../util'; | ||
| import type { Range } from 'vscode-languageserver'; | ||
|
|
@@ -11,7 +11,7 @@ | |
| import { InternalWalkMode, walk, createVisitor, WalkMode, walkArray } from '../astUtils/visitors'; | ||
| import { isCallExpression, isCommentStatement, isEnumMemberStatement, isExpression, isExpressionStatement, isFieldStatement, isFunctionExpression, isFunctionStatement, isIfStatement, isInterfaceFieldStatement, isInterfaceMethodStatement, isInvalidType, isLiteralExpression, isMethodStatement, isNamespaceStatement, isTypedefProvider, isUnaryExpression, isVoidType } from '../astUtils/reflection'; | ||
| import type { TranspileResult, TypedefProvider } from '../interfaces'; | ||
| import { createInvalidLiteral, createMethodStatement, createToken } from '../astUtils/creators'; | ||
| import { createIdentifier, createInvalidLiteral, createMethodStatement, createToken } from '../astUtils/creators'; | ||
| import { DynamicType } from '../types/DynamicType'; | ||
| import type { BscType } from '../types/BscType'; | ||
| import type { TranspileState } from './TranspileState'; | ||
|
|
@@ -2173,6 +2173,23 @@ | |
| }) as MethodStatement; | ||
| } | ||
|
|
||
| /** | ||
| * Return the parameters for the first constructor function for this class | ||
| * @param ancestors The list of ancestors for this class | ||
| * @returns The parameters for the first constructor function for this class | ||
| */ | ||
| private getConstructorParams(ancestors: ClassStatement[]) { | ||
| for (let ancestor of ancestors) { | ||
| // @todo: somehow, ancestors can have a list where the last element is null. | ||
| // this is exposed by the test named "extending namespaced class transpiles properly". | ||
|
||
| if (ancestor) { | ||
| const ctor = ancestor.getConstructorFunction(); | ||
| if (ctor) return ctor.func.parameters; | ||
| } | ||
| } | ||
| return []; | ||
| } | ||
|
|
||
| /** | ||
| * Determine if the specified field was declared in one of the ancestor classes | ||
| */ | ||
|
|
@@ -2226,10 +2243,38 @@ | |
| let body = this.body; | ||
| //inject an empty "new" method if missing | ||
| if (!this.getConstructorFunction()) { | ||
| body = [ | ||
| createMethodStatement('new', TokenKind.Sub), | ||
| ...this.body | ||
| ]; | ||
| if (ancestors.length == 0) { | ||
| body = [ | ||
| createMethodStatement('new', TokenKind.Sub), | ||
| ...this.body | ||
| ]; | ||
| } else { | ||
| const params = this.getConstructorParams(ancestors); | ||
| const call = new ExpressionStatement( | ||
| new CallExpression( | ||
| new VariableExpression(createToken(TokenKind.Identifier, 'super')), | ||
| createToken(TokenKind.LeftParen), | ||
| createToken(TokenKind.RightParen), | ||
| params.map(x => new VariableExpression(x.name)) | ||
| ) | ||
| ); | ||
| body = [ | ||
| new MethodStatement( | ||
| [], | ||
| createIdentifier('new'), | ||
| new FunctionExpression( | ||
| params.map(x => x.clone()), | ||
| new Block([call]), | ||
| createToken(TokenKind.Sub), | ||
| createToken(TokenKind.EndSub), | ||
| createToken(TokenKind.LeftParen), | ||
| createToken(TokenKind.RightParen) | ||
| ), | ||
| null | ||
| ), | ||
| ...this.body | ||
| ]; | ||
| } | ||
| } | ||
|
|
||
| for (let statement of body) { | ||
|
|
@@ -2289,8 +2334,14 @@ | |
| */ | ||
| private getTranspiledClassFunction(state: BrsTranspileState) { | ||
| let result = [] as TranspileResult; | ||
|
|
||
| const constructorFunction = this.getConstructorFunction(); | ||
| const constructorParams = constructorFunction ? constructorFunction.func.parameters : []; | ||
| let constructorParams = []; | ||
| if (constructorFunction) { | ||
| constructorParams = constructorFunction.func.parameters; | ||
| } else { | ||
| constructorParams = this.getConstructorParams(this.getAncestors(state)); | ||
| } | ||
|
|
||
| result.push( | ||
| state.sourceNode(this.classKeyword, 'function'), | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.