Skip to content

Commit

Permalink
Add generic type param for addReplaceFile.
Browse files Browse the repository at this point in the history
Export `BscType` type for `BrsFile | XmlFile`
  • Loading branch information
TwitchBronBron committed Oct 10, 2020
1 parent 1cb7769 commit 6b7ba1f
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 110 deletions.
14 changes: 7 additions & 7 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@ export interface CompilerPlugin {
beforeScopeValidate?: ValidateHandler;
afterScopeValidate?: ValidateHandler;
beforeFileParse?: (source: SourceObj) => void;
afterFileParse?: (file: (BrsFile | XmlFile)) => void;
afterFileValidate?: (file: (BrsFile | XmlFile)) => void;
afterFileParse?: (file: BscFile) => void;
afterFileValidate?: (file: BscFile) => void;
beforeFileTranspile?: (entry: TranspileObj) => void;
afterFileTranspile?: (entry: TranspileObj) => void;
beforeFileDispose?: (file: (BrsFile | XmlFile)) => void;
afterFileDispose?: (file: (BrsFile | XmlFile)) => void;
beforeFileDispose?: (file: BscFile) => void;
afterFileDispose?: (file: BscFile) => void;
}

// related types:
Expand All @@ -149,11 +149,11 @@ interface SourceObj {
}

interface TranspileObj {
file: (BrsFile | XmlFile);
file: (BscFile);
outputPath: string;
}

type ValidateHandler = (scope: Scope, files: (BrsFile | XmlFile)[], callables: CallableContainerMap) => void;
type ValidateHandler = (scope: Scope, files: BscFile[], callables: CallableContainerMap) => void;
interface CallableContainerMap {
[name: string]: CallableContainer[];
}
Expand Down Expand Up @@ -206,7 +206,7 @@ const pluginInterface: CompilerPlugin = {
export default pluginInterface;

// post-parsing validation
function afterFileValidate(file: BrsFile | XmlFile) {
function afterFileValidate(file: BscFile) {
if (!isBrsFile(file)) {
return;
}
Expand Down
34 changes: 17 additions & 17 deletions src/Program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Scope } from './Scope';
import { DiagnosticMessages } from './DiagnosticMessages';
import { BrsFile } from './files/BrsFile';
import { XmlFile } from './files/XmlFile';
import { BsDiagnostic, File, FileReference, FileObj } from './interfaces';
import { BsDiagnostic, File, FileReference, FileObj, BscFile } from './interfaces';
import { standardizePath as s, util } from './util';
import { XmlScope } from './XmlScope';
import { DiagnosticFilterer } from './DiagnosticFilterer';
Expand All @@ -27,7 +27,7 @@ export interface SourceObj {
}

export interface TranspileObj {
file: (BrsFile | XmlFile);
file: BscFile;
outputPath: string;
}

Expand Down Expand Up @@ -111,7 +111,7 @@ export class Program {
/**
* A map of every file loaded into this program
*/
public files = {} as { [pathAbsolute: string]: BrsFile | XmlFile };
public files = {} as { [pathAbsolute: string]: BscFile };

private scopes = {} as { [name: string]: Scope };

Expand Down Expand Up @@ -235,14 +235,14 @@ export class Program {
* contents from the file system.
* @param filePaths
*/
public async addOrReplaceFiles(fileObjects: Array<FileObj>) {
public async addOrReplaceFiles<T extends BscFile[]>(fileObjects: Array<FileObj>) {
let promises = [];
for (let fileObject of fileObjects) {
promises.push(
this.addOrReplaceFile(fileObject)
);
}
return Promise.all(promises);
return Promise.all(promises) as Promise<T>;
}

public getPkgPath(...args: any[]): any { //eslint-disable-line
Expand Down Expand Up @@ -284,15 +284,15 @@ export class Program {
* @param relativePath the file path relative to the root dir
* @param fileContents the file contents. If not provided, the file will be loaded from disk
*/
public async addOrReplaceFile(relativePath: string, fileContents?: string): Promise<XmlFile | BrsFile>;
public async addOrReplaceFile<T extends BscFile>(relativePath: string, fileContents?: string): Promise<T>;
/**
* Load a file into the program. If that file already exists, it is replaced.
* If file contents are provided, those are used, Otherwise, the file is loaded from the file system
* @param fileEntry an object that specifies src and dest for the file.
* @param fileContents the file contents. If not provided, the file will be loaded from disk
*/
public async addOrReplaceFile(fileEntry: FileObj, fileContents?: string): Promise<XmlFile | BrsFile>;
public async addOrReplaceFile(fileParam: FileObj | string, fileContents?: string): Promise<XmlFile | BrsFile> {
public async addOrReplaceFile<T extends BscFile>(fileEntry: FileObj, fileContents?: string): Promise<T>;
public async addOrReplaceFile<T extends BscFile>(fileParam: FileObj | string, fileContents?: string): Promise<T> {
assert.ok(fileParam, 'fileEntry is required');
let pathAbsolute: string;
let pkgPath: string;
Expand All @@ -313,7 +313,7 @@ export class Program {
this.removeFile(pathAbsolute);
}
let fileExtension = path.extname(pathAbsolute).toLowerCase();
let file: BrsFile | XmlFile | undefined;
let file: BscFile | undefined;

//load the file contents by file path if not provided
let getFileContents = async () => {
Expand Down Expand Up @@ -391,7 +391,7 @@ export class Program {
}
return file;
});
return file;
return file as T;
}

/**
Expand Down Expand Up @@ -424,7 +424,7 @@ export class Program {
* Get a list of files for the given pkgPath array.
* Missing files are just ignored.
*/
public getFilesByPkgPaths(pkgPaths: string[]) {
public getFilesByPkgPaths<T extends BscFile[]>(pkgPaths: string[]) {
pkgPaths = pkgPaths.map(x => s`${x}`.toLowerCase());

let result = [] as Array<XmlFile | BrsFile>;
Expand All @@ -434,15 +434,15 @@ export class Program {
result.push(file);
}
}
return result;
return result as T;
}

/**
* Get a file with the specified pkg path.
* If not found, return undefined
*/
public getFileByPkgPath(pkgPath: string) {
return this.getFilesByPkgPaths([pkgPath])[0];
public getFileByPkgPath<T extends BscFile>(pkgPath: string) {
return this.getFilesByPkgPaths([pkgPath])[0] as T;
}

/**
Expand Down Expand Up @@ -573,7 +573,7 @@ export class Program {
/**
* Determine if the given file is included in at least one scope in this program
*/
private fileIsIncludedInAnyScope(file: BrsFile | XmlFile) {
private fileIsIncludedInAnyScope(file: BscFile) {
for (let scopeName in this.scopes) {
if (this.scopes[scopeName].hasFile(file)) {
return true;
Expand All @@ -586,9 +586,9 @@ export class Program {
* Get the file at the given path
* @param pathAbsolute
*/
private getFile(pathAbsolute: string) {
private getFile<T extends BscFile>(pathAbsolute: string) {
pathAbsolute = s`${pathAbsolute}`;
return this.files[pathAbsolute];
return this.files[pathAbsolute] as T;
}

/**
Expand Down
24 changes: 11 additions & 13 deletions src/Scope.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { CompletionItem, CompletionItemKind, Location, Position, Range } from 'vscode-languageserver';
import chalk from 'chalk';
import { DiagnosticMessages, DiagnosticInfo } from './DiagnosticMessages';
import { BrsFile } from './files/BrsFile';
import { XmlFile } from './files/XmlFile';
import { CallableContainer, BsDiagnostic, FileReference } from './interfaces';
import { CallableContainer, BsDiagnostic, FileReference, BscFile } from './interfaces';
import { Program } from './Program';
import { BsClassValidator } from './validators/ClassValidator';
import { NamespaceStatement, ParseMode, Statement, NewExpression, FunctionStatement, ClassStatement } from './parser';
Expand Down Expand Up @@ -131,7 +129,7 @@ export class Scope {

public getFiles() {
return this.cache.getOrAdd('files', () => {
let result = [] as Array<BrsFile | XmlFile>;
let result = [] as BscFile[];
let dependencies = this.program.dependencyGraph.getAllDependencies(this.dependencyGraphKey);
for (let dependency of dependencies) {
//skip scopes and components
Expand Down Expand Up @@ -380,7 +378,7 @@ export class Scope {
this.cache.clear();
}

private detectVariableNamespaceCollisions(file: BrsFile | XmlFile) {
private detectVariableNamespaceCollisions(file: BscFile) {
//find all function parameters
for (let func of file.parser.references.functionExpressions) {
for (let param of func.parameters) {
Expand Down Expand Up @@ -428,7 +426,7 @@ export class Scope {
/**
* Find function declarations with the same name as a stdlib function
*/
private diagnosticDetectFunctionCollisions(file: BrsFile | XmlFile) {
private diagnosticDetectFunctionCollisions(file: BscFile) {
for (let func of file.callables) {
if (globalCallableMap[func.getName(ParseMode.BrighterScript).toLowerCase()]) {
this.diagnostics.push({
Expand Down Expand Up @@ -464,7 +462,7 @@ export class Scope {
* @param file
* @param callableContainersByLowerName
*/
private diagnosticDetectFunctionCallsWithWrongParamCount(file: BrsFile | XmlFile, callableContainersByLowerName: { [lowerName: string]: CallableContainer[] }) {
private diagnosticDetectFunctionCallsWithWrongParamCount(file: BscFile, callableContainersByLowerName: { [lowerName: string]: CallableContainer[] }) {
//validate all function calls
for (let expCall of file.functionCalls) {
let callableContainersWithThisName = callableContainersByLowerName[expCall.name.toLowerCase()];
Expand Down Expand Up @@ -503,7 +501,7 @@ export class Scope {
* @param file
* @param callableContainerMap
*/
private diagnosticDetectShadowedLocalVars(file: BrsFile | XmlFile, callableContainerMap: { [lowerName: string]: CallableContainer[] }) {
private diagnosticDetectShadowedLocalVars(file: BscFile, callableContainerMap: { [lowerName: string]: CallableContainer[] }) {
//loop through every function scope
for (let scope of file.functionScopes) {
//every var declaration in this scope
Expand Down Expand Up @@ -558,7 +556,7 @@ export class Scope {
* @param file
* @param callablesByLowerName
*/
private diagnosticDetectCallsToUnknownFunctions(file: BrsFile | XmlFile, callablesByLowerName: { [lowerName: string]: CallableContainer[] }) {
private diagnosticDetectCallsToUnknownFunctions(file: BscFile, callablesByLowerName: { [lowerName: string]: CallableContainer[] }) {
//validate all expression calls
for (let expCall of file.functionCalls) {
let lowerName = expCall.name.toLowerCase();
Expand Down Expand Up @@ -727,7 +725,7 @@ export class Scope {
* Determine if this scope is referenced and known by the file.
* @param file
*/
public hasFile(file: BrsFile | XmlFile) {
public hasFile(file: BscFile) {
let files = this.getFiles();
let hasFile = files.includes(file);
return hasFile;
Expand Down Expand Up @@ -759,7 +757,7 @@ export class Scope {
/**
* Get the definition (where was this thing first defined) of the symbol under the position
*/
public getDefinition(file: BrsFile | XmlFile, position: Position): Location[] { //eslint-disable-line
public getDefinition(file: BscFile, position: Position): Location[] { //eslint-disable-line
//TODO implement for brs files
return [];
}
Expand All @@ -778,7 +776,7 @@ export class Scope {
}

interface NamespaceContainer {
file: BrsFile | XmlFile;
file: BscFile;
fullName: string;
nameRange: Range;
lastPartName: string;
Expand All @@ -789,5 +787,5 @@ interface NamespaceContainer {
}

interface AugmentedNewExpression extends NewExpression {
file: BrsFile | XmlFile;
file: BscFile;
}
8 changes: 4 additions & 4 deletions src/XmlScope.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@ describe('XmlScope', () => {

describe('constructor', () => {
it('listens for attach/detach parent events', async () => {
let parentXmlFile = await program.addOrReplaceFile('components/parent.xml', `
let parentXmlFile = await program.addOrReplaceFile<XmlFile>('components/parent.xml', `
<?xml version="1.0" encoding="utf-8" ?>
<component name="Parent" extends="Scene">
</component>
`) as XmlFile;
`);
let scope = program.getScopeByName(parentXmlFile.pkgPath);

//should default to global scope
expect(scope.getParentScope()).to.equal(program.globalScope);

let childXmlFile = await program.addOrReplaceFile('components/child.xml', `
let childXmlFile = await program.addOrReplaceFile<XmlFile>('components/child.xml', `
<?xml version="1.0" encoding="utf-8" ?>
<component name="Child" extends="Parent">
</component>
`) as XmlFile;
`);
let childScope = program.getComponentScope('Child');

await program.validate();
Expand Down
7 changes: 3 additions & 4 deletions src/XmlScope.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Location, Position } from 'vscode-languageserver';
import { Scope } from './Scope';
import { DiagnosticMessages } from './DiagnosticMessages';
import { BrsFile } from './files/BrsFile';
import { XmlFile } from './files/XmlFile';
import { FileReference } from './interfaces';
import { BscFile, FileReference } from './interfaces';
import { Program } from './Program';
import util from './util';
import { isXmlFile } from './astUtils/reflection';
Expand Down Expand Up @@ -85,7 +84,7 @@ export class XmlScope extends Scope {
return this.cache.getOrAdd('files', () => {
let result = [
this.xmlFile
] as Array<BrsFile | XmlFile>;
] as BscFile[];
let scriptPkgPaths = this.xmlFile.getAllScriptImports();
for (let scriptPkgPath of scriptPkgPaths) {
let file = this.program.getFileByPkgPath(scriptPkgPath);
Expand All @@ -100,7 +99,7 @@ export class XmlScope extends Scope {
/**
* Get the definition (where was this thing first defined) of the symbol under the position
*/
public getDefinition(file: BrsFile | XmlFile, position: Position): Location[] {
public getDefinition(file: BscFile, position: Position): Location[] {
let results = [] as Location[];
//if the position is within the file's parent component name
if (
Expand Down
6 changes: 3 additions & 3 deletions src/astUtils/reflection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import { BrsFile } from '../files/BrsFile';
import { XmlFile } from '../files/XmlFile';
import { InternalWalkMode } from './visitors';
import { FunctionType } from '../types/FunctionType';
import { File } from '../interfaces';
import { BscFile, File } from '../interfaces';
import { StringType } from '../types/StringType';

// File reflection

export function isBrsFile(file: (BrsFile | XmlFile | File)): file is BrsFile {
export function isBrsFile(file: (BscFile | File)): file is BrsFile {
return file?.constructor.name === 'BrsFile';
}

export function isXmlFile(file: (BrsFile | XmlFile)): file is XmlFile {
export function isXmlFile(file: (BscFile)): file is XmlFile {
return file?.constructor.name === 'XmlFile';
}

Expand Down
6 changes: 3 additions & 3 deletions src/astUtils/visitors.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ describe('astUtils visitors', () => {

describe('walk', () => {
async function testWalk(text: string, expectedConstructors: string[], walkMode = WalkMode.visitAllRecursive) {
const file = await program.addOrReplaceFile('source/main.bs', text) as BrsFile;
const file = await program.addOrReplaceFile<BrsFile>('source/main.bs', text);
const items = [];
let index = 1;
file.ast.walk((element: any) => {
Expand All @@ -325,14 +325,14 @@ describe('astUtils visitors', () => {
}

it('Walks through all expressions until cancelled', async () => {
const file = await program.addOrReplaceFile('source/main.bs', `
const file = await program.addOrReplaceFile<BrsFile>('source/main.bs', `
sub logger(message = "nil" as string)
innerLog = sub(message = "nil" as string)
print message
end sub
innerLog(message)
end sub
`) as BrsFile;
`);

const cancel = new CancellationTokenSource();
let count = 0;
Expand Down
6 changes: 2 additions & 4 deletions src/examples/plugins/removePrint.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { isBrsFile } from '../../astUtils/reflection';
import { createVisitor, WalkMode } from '../../astUtils/visitors';
import { BrsFile } from '../../files/BrsFile';
import { XmlFile } from '../../files/XmlFile';
import { CompilerPlugin } from '../../interfaces';
import { BscFile, CompilerPlugin } from '../../interfaces';
import { EmptyStatement } from '../../parser/Statement';

// entry point
Expand All @@ -14,7 +12,7 @@ export default pluginInterface;

// note: it is normally not recommended to modify the AST too much at this stage,
// because if the plugin runs in a language-server context it could break intellisense
function afterFileParse(file: (BrsFile | XmlFile)) {
function afterFileParse(file: BscFile) {
if (!isBrsFile(file)) {
return;
}
Expand Down

0 comments on commit 6b7ba1f

Please sign in to comment.