From 3386eb89586e037daaf5431c6bd11d6cb400c01b Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Sat, 10 Jun 2023 18:33:53 -0400 Subject: [PATCH] Convert plugin params to single event object (#824) --- src/LanguageServer.spec.ts | 3 +- src/PluginInterface.spec.ts | 11 +- src/Program.spec.ts | 6 +- src/Program.ts | 78 +++++++---- src/ProgramBuilder.ts | 28 +++- src/Scope.spec.ts | 12 +- src/Scope.ts | 12 +- src/astUtils/visitors.spec.ts | 8 +- src/bscPlugin/BscPlugin.ts | 7 +- .../BrsFileSemanticTokensProcessor.spec.ts | 1 - src/bscPlugin/validation/ProgramValidator.ts | 14 +- src/files/BrsFile.spec.ts | 2 +- src/files/XmlFile.spec.ts | 17 +-- src/interfaces.ts | 121 ++++++++++++++---- 14 files changed, 215 insertions(+), 105 deletions(-) diff --git a/src/LanguageServer.spec.ts b/src/LanguageServer.spec.ts index 1a07075a7..7b958d69f 100644 --- a/src/LanguageServer.spec.ts +++ b/src/LanguageServer.spec.ts @@ -1072,7 +1072,8 @@ describe('LanguageServer', () => { //make a plugin that changes string text server.projects[0].builder.program.plugins.add({ name: 'test-plugin', - beforeProgramTranspile: (program, entries, editor) => { + beforeProgramTranspile: (event) => { + const { program, editor } = event; const file = program.getFile('source/main.bs'); if (isBrsFile(file)) { file.ast.walk(createVisitor({ diff --git a/src/PluginInterface.spec.ts b/src/PluginInterface.spec.ts index 47fd4fea1..4ea4b239d 100644 --- a/src/PluginInterface.spec.ts +++ b/src/PluginInterface.spec.ts @@ -16,9 +16,9 @@ describe('PluginInterface', () => { name: 'allows adding a plugin', beforePublish: beforePublish }; - pluginInterface.emit('beforePublish', undefined, []); + pluginInterface.emit('beforePublish', { builder: undefined, program: undefined, files: [] }); pluginInterface.add(plugin); - pluginInterface.emit('beforePublish', undefined, []); + pluginInterface.emit('beforePublish', { builder: undefined, program: undefined, files: [] }); expect(beforePublish.callCount).to.equal(1); }); @@ -39,7 +39,8 @@ describe('PluginInterface', () => { }; pluginInterface.add(plugin); pluginInterface.add(plugin); - pluginInterface.emit('beforePublish', undefined, []); + pluginInterface.emit('beforePublish', { builder: undefined, program: undefined, files: [] }); + expect(beforePublish.callCount).to.equal(1); pluginInterface.remove(plugin); expect(pluginInterface.has(plugin)).to.be.false; @@ -52,10 +53,10 @@ describe('PluginInterface', () => { beforePublish: beforePublish }; pluginInterface.add(plugin); - pluginInterface.emit('beforePublish', undefined, []); + pluginInterface.emit('beforePublish', { builder: undefined, program: undefined, files: [] }); expect(beforePublish.callCount).to.equal(1); pluginInterface.remove(plugin); - pluginInterface.emit('beforePublish', undefined, []); + pluginInterface.emit('beforePublish', { builder: undefined, program: undefined, files: [] }); expect(beforePublish.callCount).to.equal(1); }); }); diff --git a/src/Program.spec.ts b/src/Program.spec.ts index c9a59f5c7..a0d15d054 100644 --- a/src/Program.spec.ts +++ b/src/Program.spec.ts @@ -6,7 +6,6 @@ import * as fsExtra from 'fs-extra'; import { DiagnosticMessages } from './DiagnosticMessages'; import type { BrsFile } from './files/BrsFile'; import type { XmlFile } from './files/XmlFile'; -import type { TranspileObj } from './Program'; import { Program } from './Program'; import { standardizePath as s, util } from './util'; import { URI } from 'vscode-uri'; @@ -19,7 +18,6 @@ import { Logger } from './Logger'; import { createVisitor, WalkMode } from './astUtils/visitors'; import { isBrsFile } from './astUtils/reflection'; import type { LiteralExpression } from './parser/Expression'; -import type { AstEditor } from './astUtils/AstEditor'; import { tempDir, rootDir, stagingDir } from './testHelpers.spec'; let sinon = sinonImport.createSandbox(); @@ -1951,11 +1949,11 @@ describe('Program', () => { //replace all strings with "goodbye world" program.plugins.add({ name: 'TestPlugin', - beforeProgramTranspile: (program: Program, entries: TranspileObj[], editor: AstEditor) => { + beforeProgramTranspile: (event) => { file.ast.walk(createVisitor({ LiteralExpression: (literal) => { literalExpression = literal; - editor.setProperty(literal.token, 'text', '"goodbye world"'); + event.editor.setProperty(literal.token, 'text', '"goodbye world"'); } }), { walkMode: WalkMode.visitExpressionsRecursive diff --git a/src/Program.ts b/src/Program.ts index eea32bb22..b99a41283 100644 --- a/src/Program.ts +++ b/src/Program.ts @@ -8,7 +8,7 @@ import { Scope } from './Scope'; import { DiagnosticMessages } from './DiagnosticMessages'; import { BrsFile } from './files/BrsFile'; import { XmlFile } from './files/XmlFile'; -import type { BsDiagnostic, File, FileReference, FileObj, BscFile, SemanticToken, AfterFileTranspileEvent, FileLink, ProvideHoverEvent, ProvideCompletionsEvent, Hover } from './interfaces'; +import type { BsDiagnostic, File, FileReference, FileObj, BscFile, SemanticToken, AfterFileTranspileEvent, FileLink, ProvideHoverEvent, ProvideCompletionsEvent, Hover, BeforeFileParseEvent } from './interfaces'; import { standardizePath as s, util } from './util'; import { XmlScope } from './XmlScope'; import { DiagnosticFilterer } from './DiagnosticFilterer'; @@ -203,7 +203,10 @@ export class Program { protected addScope(scope: Scope) { this.scopes[scope.name] = scope; - this.plugins.emit('afterScopeCreate', scope); + this.plugins.emit('afterScopeCreate', { + program: this, + scope: scope + }); } /** @@ -445,18 +448,22 @@ export class Program { this.dependencyGraph.addDependency('scope:source', brsFile.dependencyGraphKey); } - let sourceObj: SourceObj = { + let beforeFileParseEvent: BeforeFileParseEvent = { + program: this, srcPath: srcPath, source: fileContents }; - this.plugins.emit('beforeFileParse', sourceObj); + this.plugins.emit('beforeFileParse', beforeFileParseEvent); this.logger.time(LogLevel.debug, ['parse', chalk.green(srcPath)], () => { - brsFile.parse(sourceObj.source); + brsFile.parse(beforeFileParseEvent.source); }); //notify plugins that this file has finished parsing - this.plugins.emit('afterFileParse', brsFile); + this.plugins.emit('afterFileParse', { + program: this, + file: brsFile + }); file = brsFile; @@ -473,18 +480,22 @@ export class Program { new XmlFile(srcPath, pkgPath, this) ); - let sourceObj: SourceObj = { + let event: BeforeFileParseEvent = { + program: this, srcPath: srcPath, source: fileContents }; - this.plugins.emit('beforeFileParse', sourceObj); + this.plugins.emit('beforeFileParse', event); this.logger.time(LogLevel.debug, ['parse', chalk.green(srcPath)], () => { - xmlFile.parse(sourceObj.source); + xmlFile.parse(event.source); }); //notify plugins that this file has finished parsing - this.plugins.emit('afterFileParse', xmlFile); + this.plugins.emit('afterFileParse', { + program: this, + file: xmlFile + }); file = xmlFile; @@ -606,17 +617,25 @@ export class Program { let file = this.getFile(filePath, normalizePath); if (file) { - this.plugins.emit('beforeFileDispose', file); + const fileDisposeEvent = { + program: this, + file: file + }; + this.plugins.emit('beforeFileDispose', fileDisposeEvent); //if there is a scope named the same as this file's path, remove it (i.e. xml scopes) let scope = this.scopes[file.pkgPath]; if (scope) { - this.plugins.emit('beforeScopeDispose', scope); + const scopeDisposeEvent = { + program: this, + scope: scope + }; + this.plugins.emit('beforeScopeDispose', scopeDisposeEvent); scope.dispose(); //notify dependencies of this scope that it has been removed this.dependencyGraph.remove(scope.dependencyGraphKey); delete this.scopes[file.pkgPath]; - this.plugins.emit('afterScopeDispose', scope); + this.plugins.emit('afterScopeDispose', scopeDisposeEvent); } //remove the file from the program this.unassignFile(file); @@ -634,7 +653,7 @@ export class Program { } //dispose file file?.dispose(); - this.plugins.emit('afterFileDispose', file); + this.plugins.emit('afterFileDispose', fileDisposeEvent); } } @@ -644,25 +663,26 @@ export class Program { public validate() { this.logger.time(LogLevel.log, ['Validating project'], () => { this.diagnostics = []; - this.plugins.emit('beforeProgramValidate', this); + const programValidateEvent = { + program: this + }; + this.plugins.emit('beforeProgramValidate', programValidateEvent); //validate every file for (const file of Object.values(this.files)) { //for every unvalidated file, validate it if (!file.isValidated) { - this.plugins.emit('beforeFileValidate', { + const validateFileEvent = { program: this, file: file - }); + }; + this.plugins.emit('beforeFileValidate', validateFileEvent); //emit an event to allow plugins to contribute to the file validation process - this.plugins.emit('onFileValidate', { - program: this, - file: file - }); + this.plugins.emit('onFileValidate', validateFileEvent); file.isValidated = true; - this.plugins.emit('afterFileValidate', file); + this.plugins.emit('afterFileValidate', validateFileEvent); } } @@ -677,7 +697,7 @@ export class Program { this.detectDuplicateComponentNames(); - this.plugins.emit('afterProgramValidate', this); + this.plugins.emit('afterProgramValidate', programValidateEvent); }); } @@ -1172,7 +1192,11 @@ export class Program { const astEditor = new AstEditor(); - this.plugins.emit('beforeProgramTranspile', this, entries, astEditor); + this.plugins.emit('beforeProgramTranspile', { + program: this, + entries: entries, + editor: astEditor + }); return { entries: entries, getOutputPath: getOutputPath, @@ -1249,7 +1273,11 @@ export class Program { } private afterProgramTranspile(entries: TranspileObj[], astEditor: AstEditor) { - this.plugins.emit('afterProgramTranspile', this, entries, astEditor); + this.plugins.emit('afterProgramTranspile', { + program: this, + entries: entries, + editor: astEditor + }); astEditor.undoAll(); } diff --git a/src/ProgramBuilder.ts b/src/ProgramBuilder.ts index 2aa162d1f..307691ec8 100644 --- a/src/ProgramBuilder.ts +++ b/src/ProgramBuilder.ts @@ -145,7 +145,10 @@ export class ProgramBuilder { protected createProgram() { const program = new Program(this.options, undefined, this.plugins); - this.plugins.emit('afterProgramCreate', program); + this.plugins.emit('afterProgramCreate', { + builder: this, + program: program + }); return program; } @@ -161,7 +164,9 @@ export class ProgramBuilder { this.plugins.add(plugin); } - this.plugins.emit('beforeProgramCreate', this); + this.plugins.emit('beforeProgramCreate', { + builder: this + }); } /** @@ -417,8 +422,12 @@ export class ProgramBuilder { filteredFileMap.push(fileEntry); } } - - this.plugins.emit('beforePrepublish', this, filteredFileMap); + const prepublishEvent = { + builder: this, + program: this.program, + files: filteredFileMap + }; + this.plugins.emit('beforePrepublish', prepublishEvent); await this.logger.time(LogLevel.log, ['Copying to staging directory'], async () => { //prepublish all non-program-loaded files to staging @@ -428,15 +437,20 @@ export class ProgramBuilder { }); }); - this.plugins.emit('afterPrepublish', this, filteredFileMap); - this.plugins.emit('beforePublish', this, fileMap); + this.plugins.emit('afterPrepublish', prepublishEvent); + const publishEvent = { + builder: this, + program: this.program, + files: fileMap + }; + this.plugins.emit('beforePublish', publishEvent); await this.logger.time(LogLevel.log, ['Transpiling'], async () => { //transpile any brighterscript files await this.program.transpile(fileMap, options.stagingDir); }); - this.plugins.emit('afterPublish', this, fileMap); + this.plugins.emit('afterPublish', publishEvent); }); } diff --git a/src/Scope.spec.ts b/src/Scope.spec.ts index cd2a16f18..28e26c0a4 100644 --- a/src/Scope.spec.ts +++ b/src/Scope.spec.ts @@ -1135,20 +1135,22 @@ describe('Scope', () => { afterScopeValidate: sinon.spy() }); program.validate(); - const scopeNames = program.getScopes().map(x => x.name).filter(x => x !== 'global').sort(); + let scopeNames = program.getScopes().map(x => x.name).filter(x => x !== 'global').sort(); + const scopes = plugin.beforeScopeValidate.getCalls().map(x => x.args[0].scope); expect(plugin.beforeScopeValidate.callCount).to.equal(2); - expect(plugin.beforeScopeValidate.calledWith(sourceScope)).to.be.true; - expect(plugin.beforeScopeValidate.calledWith(compScope)).to.be.true; + expect(scopes).to.include(sourceScope); + expect(scopes).to.include(compScope); expect(plugin.onScopeValidate.callCount).to.equal(2); expect(plugin.onScopeValidate.getCalls().map( x => (x.args[0] as OnScopeValidateEvent).scope.name ).sort()).to.eql(scopeNames); + scopeNames = program.getScopes().map(x => x.name).filter(x => x !== 'global').sort(); expect(plugin.afterScopeValidate.callCount).to.equal(2); - expect(plugin.afterScopeValidate.calledWith(sourceScope)).to.be.true; - expect(plugin.afterScopeValidate.calledWith(compScope)).to.be.true; + expect(scopes).to.include(sourceScope); + expect(scopes).to.include(compScope); }); it('supports parameter types in functions in AA literals defined in other scope', () => { diff --git a/src/Scope.ts b/src/Scope.ts index 241270be0..0895e9d6a 100644 --- a/src/Scope.ts +++ b/src/Scope.ts @@ -698,19 +698,19 @@ export class Scope { //get a list of all callables, indexed by their lower case names let callableContainerMap = util.getCallableContainersByLowerName(callables); - let files = this.getOwnFiles(); //Since statements from files are shared across multiple scopes, we need to link those statements to the current scope this.linkSymbolTable(); - this.program.plugins.emit('beforeScopeValidate', this, files, callableContainerMap); - - this.program.plugins.emit('onScopeValidate', { + const scopeValidateEvent = { program: this.program, scope: this - }); + }; + this.program.plugins.emit('beforeScopeValidate', scopeValidateEvent); + + this.program.plugins.emit('onScopeValidate', scopeValidateEvent); this._validate(callableContainerMap); - this.program.plugins.emit('afterScopeValidate', this, files, callableContainerMap); + this.program.plugins.emit('afterScopeValidate', scopeValidateEvent); //unlink all symbol tables from this scope (so they don't accidentally stick around) this.unlinkSymbolTable(); diff --git a/src/astUtils/visitors.spec.ts b/src/astUtils/visitors.spec.ts index 38f2497ff..60489a32c 100644 --- a/src/astUtils/visitors.spec.ts +++ b/src/astUtils/visitors.spec.ts @@ -103,7 +103,7 @@ describe('astUtils visitors', () => { const walker = functionsWalker(visitor); program.plugins.add({ name: 'walker', - afterFileParse: file => walker(file as BrsFile) + afterFileParse: event => walker(event.file as BrsFile) }); program.setFile('source/main.brs', PRINTS_SRC); expect(actual).to.deep.equal([ @@ -140,7 +140,7 @@ describe('astUtils visitors', () => { const walker = functionsWalker(s => actual.push(s.constructor.name), cancel.token); program.plugins.add({ name: 'walker', - afterFileParse: file => walker(file as BrsFile) + afterFileParse: event => walker(event.file as BrsFile) }); program.setFile('source/main.brs', PRINTS_SRC); expect(actual).to.deep.equal([ @@ -185,7 +185,7 @@ describe('astUtils visitors', () => { }, cancel.token); program.plugins.add({ name: 'walker', - afterFileParse: file => walker(file as BrsFile) + afterFileParse: event => walker(event.file as BrsFile) }); program.setFile('source/main.brs', PRINTS_SRC); expect(actual).to.deep.equal([ @@ -291,7 +291,7 @@ describe('astUtils visitors', () => { }); program.plugins.add({ name: 'walker', - afterFileParse: (file) => walker(file as BrsFile) + afterFileParse: (event) => walker(event.file as BrsFile) }); program.setFile('source/main.brs', EXPRESSIONS_SRC); diff --git a/src/bscPlugin/BscPlugin.ts b/src/bscPlugin/BscPlugin.ts index f85e8ca81..39c56e168 100644 --- a/src/bscPlugin/BscPlugin.ts +++ b/src/bscPlugin/BscPlugin.ts @@ -1,6 +1,5 @@ import { isBrsFile, isXmlFile } from '../astUtils/reflection'; -import type { BeforeFileTranspileEvent, CompilerPlugin, OnFileValidateEvent, OnGetCodeActionsEvent, ProvideHoverEvent, OnGetSemanticTokensEvent, OnScopeValidateEvent, ProvideCompletionsEvent } from '../interfaces'; -import type { Program } from '../Program'; +import type { BeforeFileTranspileEvent, CompilerPlugin, OnFileValidateEvent, OnGetCodeActionsEvent, ProvideHoverEvent, OnGetSemanticTokensEvent, OnScopeValidateEvent, ProvideCompletionsEvent, AfterProgramValidateEvent } from '../interfaces'; import { CodeActionsProcessor } from './codeActions/CodeActionsProcessor'; import { CompletionsProcessor } from './completions/CompletionsProcessor'; import { HoverProcessor } from './hover/HoverProcessor'; @@ -47,8 +46,8 @@ export class BscPlugin implements CompilerPlugin { this.scopeValidator.processEvent(event); } - public afterProgramValidate(program: Program) { - new ProgramValidator(program).process(); + public afterProgramValidate(event: AfterProgramValidateEvent) { + new ProgramValidator(event).process(); //release memory once the validation cycle has finished this.scopeValidator.reset(); } diff --git a/src/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.ts b/src/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.ts index fc3232826..e5214b068 100644 --- a/src/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.ts +++ b/src/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.ts @@ -7,7 +7,6 @@ import { expectZeroDiagnostics } from '../../testHelpers.spec'; import { util } from '../../util'; import { rootDir } from '../../testHelpers.spec'; - describe('BrsFileSemanticTokensProcessor', () => { let program: Program; beforeEach(() => { diff --git a/src/bscPlugin/validation/ProgramValidator.ts b/src/bscPlugin/validation/ProgramValidator.ts index cf56d9766..d353e001e 100644 --- a/src/bscPlugin/validation/ProgramValidator.ts +++ b/src/bscPlugin/validation/ProgramValidator.ts @@ -1,10 +1,12 @@ import { isBrsFile } from '../../astUtils/reflection'; import { DiagnosticMessages } from '../../DiagnosticMessages'; -import type { Program } from '../../Program'; +import type { AfterProgramValidateEvent } from '../../interfaces'; import util from '../../util'; export class ProgramValidator { - constructor(private program: Program) { } + constructor( + private event: AfterProgramValidateEvent + ) { } public process() { this.flagScopelessBrsFiles(); @@ -14,19 +16,19 @@ export class ProgramValidator { * Flag any files that are included in 0 scopes. */ private flagScopelessBrsFiles() { - for (const key in this.program.files) { - const file = this.program.files[key]; + for (const key in this.event.program.files) { + const file = this.event.program.files[key]; if ( //if this isn't a brs file, skip !isBrsFile(file) || //if the file is included in at least one scope, skip - this.program.getFirstScopeForFile(file) + this.event.program.getFirstScopeForFile(file) ) { continue; } - this.program.addDiagnostics([{ + this.event.program.addDiagnostics([{ ...DiagnosticMessages.fileNotReferencedByAnyOtherFile(), file: file, range: util.createRange(0, 0, 0, Number.MAX_VALUE) diff --git a/src/files/BrsFile.spec.ts b/src/files/BrsFile.spec.ts index 4ca019d96..9758b6a28 100644 --- a/src/files/BrsFile.spec.ts +++ b/src/files/BrsFile.spec.ts @@ -3467,7 +3467,7 @@ describe('BrsFile', () => { return { name: 'lower-file-name', afterFileParse: (evt) => { - evt._customProp = true; + evt.file._customProp = true; } }; } diff --git a/src/files/XmlFile.spec.ts b/src/files/XmlFile.spec.ts index ac7e51593..ef813f1a2 100644 --- a/src/files/XmlFile.spec.ts +++ b/src/files/XmlFile.spec.ts @@ -40,7 +40,8 @@ describe('XmlFile', () => { const expected = 'OtherName'; program.plugins.add({ name: 'allows modifying the parsed XML model', - afterFileParse: (file) => { + afterFileParse: (event) => { + const file = event.file as XmlFile; if (isXmlFile(file) && file.parser.ast.rootElement?.attributes?.[0]?.value) { file.parser.ast.rootElement.attributes[0].value = expected; } @@ -643,9 +644,9 @@ describe('XmlFile', () => { it(`honors the 'needsTranspiled' flag when set in 'afterFileParse'`, () => { program.plugins.add({ name: 'test', - afterFileParse: (file) => { + afterFileParse: (event) => { //enable transpile for every file - file.needsTranspiled = true; + event.file.needsTranspiled = true; } }); const file = program.setFile('components/file.xml', trim` @@ -965,7 +966,7 @@ describe('XmlFile', () => { }); program.plugins.add({ name: 'Transform plugins', - afterFileParse: file => validateXml(file as XmlFile) + afterFileParse: event => validateXml(event.file as XmlFile) }); file = program.setFile('components/component.xml', trim` @@ -989,10 +990,10 @@ describe('XmlFile', () => { it('plugin diagnostics work for xml files', () => { program.plugins.add({ name: 'Xml diagnostic test', - afterFileParse: (file) => { - if (file.srcPath.endsWith('.xml')) { - file.addDiagnostics([{ - file: file, + afterFileParse: (event) => { + if (event.file.srcPath.endsWith('.xml')) { + event.file.addDiagnostics([{ + file: event.file, message: 'Test diagnostic', range: Range.create(0, 0, 0, 0), code: 9999 diff --git a/src/interfaces.ts b/src/interfaces.ts index a9b3d4e6f..a5b3f4d00 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -5,7 +5,7 @@ import type { XmlFile } from './files/XmlFile'; import type { FunctionScope } from './FunctionScope'; import type { FunctionType } from './types/FunctionType'; import type { ParseMode } from './parser/Parser'; -import type { Program, SourceObj, TranspileObj } from './Program'; +import type { Program } from './Program'; import type { ProgramBuilder } from './ProgramBuilder'; import type { FunctionStatement } from './parser/Statement'; import type { Expression } from './parser/AstNode'; @@ -184,23 +184,21 @@ export interface CommentFlag { codes: DiagnosticCode[] | null; } -type ValidateHandler = (scope: Scope, files: BscFile[], callables: CallableContainerMap) => void; - export type CompilerPluginFactory = () => CompilerPlugin; export interface CompilerPlugin { name: string; //program events - beforeProgramCreate?: (builder: ProgramBuilder) => void; - beforePrepublish?: (builder: ProgramBuilder, files: FileObj[]) => void; - afterPrepublish?: (builder: ProgramBuilder, files: FileObj[]) => void; - beforePublish?: (builder: ProgramBuilder, files: FileObj[]) => void; - afterPublish?: (builder: ProgramBuilder, files: FileObj[]) => void; - afterProgramCreate?: (program: Program) => void; - beforeProgramValidate?: (program: Program) => void; - afterProgramValidate?: (program: Program) => void; - beforeProgramTranspile?: (program: Program, entries: TranspileObj[], editor: AstEditor) => void; - afterProgramTranspile?: (program: Program, entries: TranspileObj[], editor: AstEditor) => void; + beforeProgramCreate?: PluginHandler; + afterProgramCreate?: PluginHandler; + beforePrepublish?: PluginHandler; + afterPrepublish?: PluginHandler; + beforePublish?: PluginHandler; + afterPublish?: PluginHandler; + beforeProgramValidate?: PluginHandler; + afterProgramValidate?: PluginHandler; + beforeProgramTranspile?: PluginHandler; + afterProgramTranspile?: PluginHandler; onGetCodeActions?: PluginHandler; /** @@ -231,15 +229,15 @@ export interface CompilerPlugin { onGetSemanticTokens?: PluginHandler; //scope events - afterScopeCreate?: (scope: Scope) => void; - beforeScopeDispose?: (scope: Scope) => void; - afterScopeDispose?: (scope: Scope) => void; - beforeScopeValidate?: ValidateHandler; + afterScopeCreate?: PluginHandler; + beforeScopeDispose?: PluginHandler; + afterScopeDispose?: PluginHandler; + beforeScopeValidate?: PluginHandler; onScopeValidate?: PluginHandler; - afterScopeValidate?: ValidateHandler; + afterScopeValidate?: PluginHandler; //file events - beforeFileParse?: (source: SourceObj) => void; - afterFileParse?: (file: BscFile) => void; + beforeFileParse?: PluginHandler; + afterFileParse?: PluginHandler; /** * Called before each file is validated */ @@ -251,14 +249,46 @@ export interface CompilerPlugin { /** * Called after each file is validated */ - afterFileValidate?: (file: BscFile) => void; + afterFileValidate?: PluginHandler; beforeFileTranspile?: PluginHandler; afterFileTranspile?: PluginHandler; - beforeFileDispose?: (file: BscFile) => void; - afterFileDispose?: (file: BscFile) => void; + beforeFileDispose?: PluginHandler; + afterFileDispose?: PluginHandler; } export type PluginHandler = (event: T) => R; +export interface BeforeProgramCreateEvent { + builder: ProgramBuilder; +} +export interface AfterProgramCreateEvent { + builder: ProgramBuilder; + program: Program; +} +export interface BeforePrepublishEvent { + builder: ProgramBuilder; + program: Program; + files: FileObj[]; +} +export type AfterPrepublishEvent = BeforePrepublishEvent; + +export interface BeforePublishEvent { + builder: ProgramBuilder; + program: Program; + files: FileObj[]; +} +export type AfterPublishEvent = BeforePublishEvent; +export interface BeforeProgramValidateEvent { + program: Program; +} +export type AfterProgramValidateEvent = BeforeProgramValidateEvent; + +export interface BeforeProgramTranspileEvent { + program: Program; + entries: TranspileEntry[]; + editor: AstEditor; +} +export type AfterProgramTranspileEvent = BeforeProgramTranspileEvent; + export interface OnGetCodeActionsEvent { program: Program; file: BscFile; @@ -303,6 +333,34 @@ export interface Hover { export type BeforeProvideHoverEvent = ProvideHoverEvent; export type AfterProvideHoverEvent = ProvideHoverEvent; +export interface AfterScopeCreateEvent { + program: Program; + scope: Scope; +} +export interface BeforeScopeDisposeEvent { + program: Program; + scope: Scope; +} +export interface AfterScopeDisposeEvent { + program: Program; + scope: Scope; +} +export interface BeforeScopeValidateEvent { + program: Program; + scope: Scope; +} +export type AfterScopeValidateEvent = BeforeScopeValidateEvent; + +export interface BeforeFileParseEvent { + program: Program; + srcPath: string; + source: string; +} +export interface AfterFileParseEvent { + program: Program; + file: BscFile; +} + export interface OnGetSemanticTokensEvent { /** * The program this file is from @@ -322,14 +380,16 @@ export interface OnGetSemanticTokensEvent { semanticTokens: SemanticToken[]; } -export interface BeforeFileValidateEvent { +export type BeforeFileValidateEvent = OnFileValidateEvent; +export interface OnFileValidateEvent { program: Program; file: T; } +export type AfterFileValidateEvent = OnFileValidateEvent; -export interface OnFileValidateEvent { - program: Program; - file: T; +export interface TranspileEntry { + file: BscFile; + outputPath: string; } export interface OnScopeValidateEvent { @@ -378,6 +438,12 @@ export interface AfterFileTranspileEvent { editor: Editor; } +export interface BeforeFileDisposeEvent { + program: Program; + file: BscFile; +} +export type AfterFileDisposeEvent = BeforeFileDisposeEvent; + export interface SemanticToken { range: Range; tokenType: SemanticTokenTypes; @@ -386,7 +452,6 @@ export interface SemanticToken { */ tokenModifiers?: SemanticTokenModifiers[]; } - export interface TypedefProvider { getTypedef(state: TranspileState): Array; }