Skip to content

Commit

Permalink
Performance fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
TwitchBronBron committed Jul 10, 2023
1 parent c6872a2 commit e5f1270
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 37 deletions.
21 changes: 21 additions & 0 deletions src/util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { NamespaceType } from './types/NamespaceType';
import { ClassType } from './types/ClassType';
import { ReferenceType } from './types/ReferenceType';
import { SymbolTypeFlag } from './SymbolTable';
import { createDottedIdentifier, createVariableExpression } from './astUtils/creators';

const sinon = createSandbox();

Expand Down Expand Up @@ -44,6 +45,26 @@ describe('util', () => {
});
});

describe('getAllDottedGetPartsAsString', () => {
it('returns undefined when no value found', () => {
expect(
util.getAllDottedGetPartsAsString(undefined)
).to.eql(undefined);
});

it('returns var name', () => {
expect(
util.getAllDottedGetPartsAsString(createVariableExpression('alpha'))
).to.eql('alpha');
});

it('returns dotted get name', () => {
expect(
util.getAllDottedGetPartsAsString(createDottedIdentifier(['alpha', 'beta']))
).to.eql('alpha.beta');
});
});

describe('diagnosticIsSuppressed', () => {
it('does not crash when diagnostic is missing location information', () => {
const program = new Program({});
Expand Down
141 changes: 104 additions & 37 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,20 @@ import { ObjectType } from './types/ObjectType';
import { StringType } from './types/StringType';
import { VoidType } from './types/VoidType';
import { ParseMode } from './parser/Parser';
import type { DottedGetExpression, VariableExpression } from './parser/Expression';
import type { CallExpression, CallfuncExpression, DottedGetExpression, FunctionParameterExpression, IndexedGetExpression, LiteralExpression, NewExpression, TypeExpression, VariableExpression, XmlAttributeGetExpression } from './parser/Expression';
import { Logger, LogLevel } from './Logger';
import type { Identifier, Locatable, Token } from './lexer/Token';
import { TokenKind } from './lexer/TokenKind';
import { isAssignmentStatement, isBrsFile, isCallExpression, isCallfuncExpression, isDottedGetExpression, isExpression, isFunctionParameterExpression, isGroupingExpression, isIndexedGetExpression, isLiteralExpression, isNewExpression, isTypeExpression, isVariableExpression, isXmlAttributeGetExpression, isXmlFile } from './astUtils/reflection';
import { isAssignmentStatement, isBrsFile, isCallExpression, isCallfuncExpression, isDottedGetExpression, isExpression, isFunctionParameterExpression, isGroupingExpression, isIndexedGetExpression, isLiteralExpression, isTypeExpression, isVariableExpression, isXmlAttributeGetExpression, isXmlFile } from './astUtils/reflection';
import { WalkMode } from './astUtils/visitors';
import { SourceNode } from 'source-map';
import * as requireRelative from 'require-relative';
import type { BrsFile } from './files/BrsFile';
import type { XmlFile } from './files/XmlFile';
import type { Expression, Statement } from './parser/AstNode';
import type { AstNode } from './parser/AstNode';
import { AstNodeKind, type Expression, type Statement } from './parser/AstNode';
import { createIdentifier } from './astUtils/creators';
import type { AssignmentStatement } from './parser/Statement';

export class Util {
public clearConsole() {
Expand Down Expand Up @@ -1332,7 +1334,52 @@ export class Util {
* @param node any ast expression
* @returns an array of the parts of the dotted get. If not fully a dotted get, then returns undefined
*/
public getAllDottedGetParts(node: Expression | Statement): Identifier[] | undefined {
public getAllDottedGetParts(node: AstNode): Identifier[] | undefined {
//this is a hot function and has been optimized. Don't rewrite unless necessary
const parts: Identifier[] = [];
let nextPart = node;
loop: while (nextPart) {
switch (nextPart?.kind) {
case AstNodeKind.AssignmentStatement:
return [(node as AssignmentStatement).name];
case AstNodeKind.DottedGetExpression:
parts.push((nextPart as DottedGetExpression)?.name);
nextPart = (nextPart as DottedGetExpression).obj;
continue;
case AstNodeKind.CallExpression:
nextPart = (nextPart as CallExpression).callee;
continue;
case AstNodeKind.TypeExpression:
nextPart = (nextPart as TypeExpression).expression;
continue;
case AstNodeKind.VariableExpression:
parts.push((nextPart as VariableExpression)?.name);
break loop;
case AstNodeKind.LiteralExpression:
parts.push((nextPart as LiteralExpression)?.token as Identifier);
break loop;
case AstNodeKind.IndexedGetExpression:
nextPart = (nextPart as IndexedGetExpression).obj;
continue;
case AstNodeKind.FunctionParameterExpression:
return [(nextPart as FunctionParameterExpression).name];
case AstNodeKind.GroupingExpression:
parts.push(createIdentifier('()', nextPart.range));
break loop;
default:
//we found a non-DottedGet expression, so return because this whole operation is invalid.
return undefined;
}
}
return parts.reverse();
}

/**
* Gets each part of the dotted get.

Check warning on line 1378 in src/util.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest)

Expected JSDoc block to be aligned

Check warning on line 1378 in src/util.ts

View workflow job for this annotation

GitHub Actions / ci (macos-latest)

Expected JSDoc block to be aligned

Check warning on line 1378 in src/util.ts

View workflow job for this annotation

GitHub Actions / ci (windows-latest)

Expected JSDoc block to be aligned
* @param node any ast expression
* @returns an array of the parts of the dotted get. If not fully a dotted get, then returns undefined
*/
public getAllDottedGetPartsOld(node: Expression | Statement): Identifier[] | undefined {
const parts: Identifier[] = [];
let nextPart = node;
while (nextPart) {
Expand Down Expand Up @@ -1366,13 +1413,31 @@ export class Util {
return parts.reverse();
}

public getAllDottedGetPartsAsString(node: Expression | Statement, parseMode = ParseMode.BrighterScript) {
const sep = parseMode === ParseMode.BrighterScript ? '.' : '_';
const hello = this.getAllDottedGetParts(node)?.map(part => part.text).join(sep);
if (!hello) {
console.log(node);
/**
* Given an expression, return all the DottedGet name parts as a string.
* Mostly used to convert namespaced item full names to a strings
*/
public getAllDottedGetPartsAsString(node: Expression | Statement, parseMode = ParseMode.BrighterScript): string {
//this is a hot function and has been optimized. Don't rewrite unless necessary
/* eslint-disable no-var */
var sep = parseMode === ParseMode.BrighterScript ? '.' : '_';
const parts = this.getAllDottedGetParts(node) ?? [];
var result = parts[0]?.text;
for (var i = 1; i < parts.length; i++) {
result += sep + parts[i].text;
}
return result;
/* eslint-enable no-var */
}

public stringJoin(strings: string[], separator: string) {
// eslint-disable-next-line no-var
var result = strings[0] ?? '';
// eslint-disable-next-line no-var
for (var i = 1; i < strings.length; i++) {
result += separator + strings[i];
}
return hello;
return result;
}

/**
Expand Down Expand Up @@ -1404,35 +1469,37 @@ export class Util {
public getDottedGetPath(expression: Expression): [VariableExpression, ...DottedGetExpression[]] {
let parts: Expression[] = [];
let nextPart = expression;
while (nextPart) {
if (isDottedGetExpression(nextPart)) {
parts.unshift(nextPart);
nextPart = nextPart.obj;

} else if (isIndexedGetExpression(nextPart) || isXmlAttributeGetExpression(nextPart)) {
nextPart = nextPart.obj;
parts = [];

} else if (isCallExpression(nextPart) || isCallfuncExpression(nextPart)) {
nextPart = nextPart.callee;
parts = [];

} else if (isNewExpression(nextPart)) {
nextPart = nextPart.call.callee;
parts = [];

} else if (isTypeExpression(nextPart)) {
nextPart = nextPart.expression;

} else if (isVariableExpression(nextPart)) {
parts.unshift(nextPart);
break;
} else {
parts = [];
break;
loop: while (nextPart) {
switch (nextPart?.kind) {
case AstNodeKind.DottedGetExpression:
parts.push(nextPart);
nextPart = (nextPart as DottedGetExpression).obj;
continue;
case AstNodeKind.IndexedGetExpression:
case AstNodeKind.XmlAttributeGetExpression:
nextPart = (nextPart as IndexedGetExpression | XmlAttributeGetExpression).obj;
parts = [];
continue;
case AstNodeKind.CallExpression:
case AstNodeKind.CallfuncExpression:
nextPart = (nextPart as CallExpression | CallfuncExpression).callee;
parts = [];
continue;
case AstNodeKind.NewExpression:
nextPart = (nextPart as NewExpression).call.callee;
parts = [];
continue;
case AstNodeKind.TypeExpression:
nextPart = (nextPart as TypeExpression).expression;
continue;
case AstNodeKind.VariableExpression:
parts.push(nextPart);
break loop;
default:
return [] as any;
}
}
return parts as any;
return parts.reverse() as any;
}

/**
Expand Down

0 comments on commit e5f1270

Please sign in to comment.