Skip to content

Commit

Permalink
Transpile files added after start of transpile cycle (#578)
Browse files Browse the repository at this point in the history
* Transpile files added after start of transpile cycle

* fix lint issues, make transpile function more consistent.
  • Loading branch information
TwitchBronBron authored Apr 30, 2022
1 parent 3624eb5 commit 3bf7bd0
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 13 deletions.
45 changes: 45 additions & 0 deletions src/Program.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,51 @@ describe('Program', () => {

describe('transpile', () => {

it('detects and transpiles files added between beforeProgramTranspile and afterProgramTranspile', async () => {
program.setFile('source/main.bs', trim`
sub main()
print "hello world"
end sub
`);
program.plugins.add({
name: 'TestPlugin',
beforeFileTranspile: (event) => {
if (isBrsFile(event.file)) {
//add lib1
if (event.outputPath.endsWith('main.brs')) {
event.program.setFile('source/lib1.bs', `
sub lib1()
end sub
`);
}
//add lib2 (this should happen during the next cycle of "catch missing files" cycle
if (event.outputPath.endsWith('main.brs')) {
//add another file
event.program.setFile('source/lib2.bs', `
sub lib2()
end sub
`);
}
}
}
});
await program.transpile([], stagingFolderPath);
//our new files should exist
expect(
fsExtra.readFileSync(`${stagingFolderPath}/source/lib1.brs`).toString()
).to.eql(trim`
sub lib1()
end sub
`);
//our changes should be there
expect(
fsExtra.readFileSync(`${stagingFolderPath}/source/lib2.brs`).toString()
).to.eql(trim`
sub lib2()
end sub
`);
});

it('sets needsTranspiled=true when there is at least one edit', async () => {
program.setFile('source/main.brs', trim`
sub main()
Expand Down
58 changes: 45 additions & 13 deletions src/Program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,7 @@ export class Program {
const editor = new AstEditor();

this.plugins.emit('beforeFileTranspile', {
program: this,
file: file,
outputPath: outputPath,
editor: editor
Expand All @@ -1288,6 +1289,7 @@ export class Program {
}

const event: AfterFileTranspileEvent = {
program: this,
file: file,
outputPath: outputPath,
editor: editor,
Expand Down Expand Up @@ -1316,7 +1318,7 @@ export class Program {
return collection;
}, {});

const entries = Object.values(this.files).map(file => {
const getOutputPath = (file: BscFile) => {
let filePathObj = mappedFileEntries[s`${file.pathAbsolute}`];
if (!filePathObj) {
//this file has been added in-memory, from a plugin, for example
Expand All @@ -1330,24 +1332,20 @@ export class Program {
let outputPath = filePathObj.dest.replace(/\.bs$/gi, '.brs');
//prepend the staging folder path
outputPath = s`${stagingFolderPath}/${outputPath}`;
return {
file: file,
outputPath: outputPath
};
});
return outputPath;
};

const astEditor = new AstEditor();
const processedFiles = new Set<File>();

this.plugins.emit('beforeProgramTranspile', this, entries, astEditor);
const transpileFile = async (file: BscFile, outputPath?: string) => {
//mark this file as processed so we don't do it again
processedFiles.add(file);

const promises = entries.map(async (entry) => {
//skip transpiling typedef files
if (isBrsFile(entry.file) && entry.file.isTypedef) {
if (isBrsFile(file) && file.isTypedef) {
return;
}

const { file, outputPath } = entry;

const fileTranspileResult = this._getTranspiledFileContents(file, outputPath);

//make sure the full dir path exists
Expand All @@ -1366,14 +1364,48 @@ export class Program {
const typedefPath = outputPath.replace(/\.brs$/i, '.d.bs');
await fsExtra.writeFile(typedefPath, fileTranspileResult.typedef);
}
};

const entries = Object.values(this.files).map(file => {
return {
file: file,
outputPath: getOutputPath(file)
};
});

const astEditor = new AstEditor();

this.plugins.emit('beforeProgramTranspile', this, entries, astEditor);

let promises = entries.map(async (entry) => {
return transpileFile(entry.file, entry.outputPath);
});

//if there's no bslib file already loaded into the program, copy it to the staging directory
if (!this.getFileByPkgPath(bslibAliasedRokuModulesPkgPath) && !this.getFileByPkgPath(s`source/bslib.brs`)) {
if (!this.getFile(bslibAliasedRokuModulesPkgPath) && !this.getFile(s`source/bslib.brs`)) {
promises.push(util.copyBslibToStaging(stagingFolderPath));
}
await Promise.all(promises);

//transpile any new files that plugins added since the start of this transpile process
do {
promises = [];
for (const key in this.files) {
const file = this.files[key];
//this is a new file
if (!processedFiles.has(file)) {
promises.push(
transpileFile(file, getOutputPath(file))
);
}
}
if (promises.length > 0) {
this.logger.info(`Transpiling ${promises.length} new files`);
await Promise.all(promises);
}
}
while (promises.length > 0);

this.plugins.emit('afterProgramTranspile', this, entries, astEditor);
astEditor.undoAll();
}
Expand Down
5 changes: 5 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ export interface OnScopeValidateEvent {
export type Editor = Pick<AstEditor, 'addToArray' | 'hasChanges' | 'removeFromArray' | 'setArrayValue' | 'setProperty' | 'overrideTranspileResult'>;

export interface BeforeFileTranspileEvent<TFile extends BscFile = BscFile> {
program: Program;
file: TFile;
outputPath: string;
/**
Expand All @@ -276,6 +277,10 @@ export interface BeforeFileTranspileEvent<TFile extends BscFile = BscFile> {
}

export interface AfterFileTranspileEvent<TFile extends BscFile = BscFile> {
/**
* The program this event was triggered for
*/
program: Program;
file: TFile;
outputPath: string;
/**
Expand Down

0 comments on commit 3bf7bd0

Please sign in to comment.