Skip to content

Commit 23b661f

Browse files
committed
Added recursion support for class methods as well
1 parent 4bee9b4 commit 23b661f

File tree

2 files changed

+58
-13
lines changed

2 files changed

+58
-13
lines changed

src/SimpleLanguageService.ts

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,7 @@ export class SimpleLanguageService implements ISimpleLanguageService {
654654
!isFunctionDeclaration(current) &&
655655
!isMethodDeclaration(current) &&
656656
!isArrowFunction(current) &&
657+
!isPropertyDeclaration(current) &&
657658
!isSourceFile(current)) {
658659
if (current.parent == null) break;
659660
current = current.parent;
@@ -680,6 +681,16 @@ export class SimpleLanguageService implements ISimpleLanguageService {
680681
return name == null ? SimpleLanguageService.GLOBAL : name;
681682
}
682683

684+
if (
685+
isPropertyDeclaration(block)
686+
) {
687+
if (block.parent == null) {
688+
const name = this.getName(block);
689+
return name == null ? SimpleLanguageService.GLOBAL : name;
690+
}
691+
return this.traceBlockScopeName(block.parent);
692+
}
693+
683694
if (isArrowFunction(block)) {
684695
return SimpleLanguageService.ANONYMOUS;
685696
}
@@ -704,14 +715,24 @@ export class SimpleLanguageService implements ISimpleLanguageService {
704715
}
705716

706717
if (
707-
isMethodDeclaration(block) ||
708718
isClassDeclaration(block) ||
709719
isClassExpression(block)
710720
) {
711721
const name = this.getName(block);
712722
return name == null ? SimpleLanguageService.GLOBAL : name;
713723
}
714724

725+
if (
726+
isMethodDeclaration(block) ||
727+
isPropertyDeclaration(block)
728+
) {
729+
if (block.parent == null) {
730+
const name = this.getName(block);
731+
return name == null ? SimpleLanguageService.GLOBAL : name;
732+
}
733+
return this.traceThis(block.parent);
734+
}
735+
715736
if (isArrowFunction(block)) {
716737
return block.parent == null ? SimpleLanguageService.GLOBAL : this.traceThis(block.parent);
717738
}
@@ -1808,7 +1829,7 @@ export class SimpleLanguageService implements ISimpleLanguageService {
18081829

18091830
else if (isIClassDeclaration(substitution)) {
18101831
const statics = part.name !== "this" && part.name === substitution.name && !hadNewExpression;
1811-
sub = this.stringifyIClassDeclaration(substitution, statics);
1832+
sub = this.stringifyIClassDeclaration(substitution, statics, part.name, scope);
18121833
}
18131834

18141835
else if (isIEnumDeclaration(substitution)) {
@@ -3329,27 +3350,30 @@ export class SimpleLanguageService implements ISimpleLanguageService {
33293350
return <string>this.marshaller.marshal<ArbitraryValue, string>(flattened, "");
33303351
}
33313352

3332-
private stringifyIClassDeclaration (classDeclaration: IClassDeclaration, statics: boolean): string {
3353+
private stringifyIClassDeclaration (classDeclaration: IClassDeclaration, statics: boolean, identifier: string, scope: string|null): string {
33333354
const map: { [key: string]: string | null | undefined } = {};
33343355

3335-
Object.keys(classDeclaration.props).forEach(propKey => {
3336-
if (statics && !classDeclaration.props[propKey].isStatic) return;
3337-
if (!statics && classDeclaration.props[propKey].isStatic) return;
3356+
for (const propKey of Object.keys(classDeclaration.props)) {
3357+
if (statics && !classDeclaration.props[propKey].isStatic) continue;
3358+
if (!statics && classDeclaration.props[propKey].isStatic) continue;
33383359

33393360
const value = classDeclaration.props[propKey].value;
33403361
map[propKey] = value.hasDoneFirstResolve() ? value.resolved : value.resolve();
3362+
}
33413363

3342-
});
3343-
3344-
Object.keys(classDeclaration.methods).forEach(methodKey => {
3345-
if (statics && !classDeclaration.methods[methodKey].isStatic) return;
3346-
if (!statics && classDeclaration.methods[methodKey].isStatic) return;
3364+
for (const methodKey of Object.keys(classDeclaration.methods)) {
3365+
if (statics && !classDeclaration.methods[methodKey].isStatic) continue;
3366+
if (!statics && classDeclaration.methods[methodKey].isStatic) continue;
33473367

33483368
const method = classDeclaration.methods[methodKey];
33493369
const value = method.value;
33503370

33513371
const hasReturnStatement = method.returnStatementStartsAt >= 0;
33523372
let resolvedValue = value.hasDoneFirstResolve() ? value.resolved : value.resolve();
3373+
3374+
// We have a self-reference here. Since 'this' refers to the mapped object, we just need to return "this".
3375+
if (identifier === "this" && scope === classDeclaration.name) return "this";
3376+
33533377
if (this.mostProbableTypeOf(resolvedValue) === "string" && resolvedValue != null && !(resolvedValue.trim().startsWith("return"))) resolvedValue = <string>this.quoteIfNecessary(resolvedValue);
33543378

33553379
const startsWithReturn = hasReturnStatement && resolvedValue != null && resolvedValue.trim().startsWith("return");
@@ -3358,8 +3382,7 @@ export class SimpleLanguageService implements ISimpleLanguageService {
33583382
const parameters = this.stringifyIParameterBody(method.parameters);
33593383

33603384
map[methodKey] = `(function ${SimpleLanguageService.FUNCTION_OUTER_SCOPE_NAME}(${parameters}) ${bracketed})`;
3361-
3362-
});
3385+
}
33633386

33643387
return <string>this.marshaller.marshal<ArbitraryValue, string>(map, "");
33653388
}

test/ResolvedValues.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,3 +545,25 @@ test(`ValueResolver -> Computes all resolved values correctly. #25`, t => {
545545
t.deepEqual(value, "28657");
546546
});
547547

548+
test(`ValueResolver -> Computes all resolved values correctly. #26`, t => {
549+
setupMany([
550+
["fibonacci", "fibonacci"],
551+
["x", "x"],
552+
["1", 1],
553+
["2", 2]
554+
]);
555+
556+
const statements = parse(`
557+
class Foo {
558+
fibonacci(x) {
559+
return x <= 1 ? x : this.fibonacci(x - 1) + this.fibonacci(x - 2);
560+
}
561+
}
562+
const foo = new Foo();
563+
const val = foo.fibonacci(23);
564+
`);
565+
566+
const assignments = service.getVariableAssignments(statements);
567+
const value = assignments["val"].value.resolve();
568+
t.deepEqual(value, "28657");
569+
});

0 commit comments

Comments
 (0)