diff --git a/client/src/input/InputStrategy.ts b/client/src/input/InputStrategy.ts index a39af22..9d4f73c 100644 --- a/client/src/input/InputStrategy.ts +++ b/client/src/input/InputStrategy.ts @@ -1,4 +1,4 @@ export default interface InputStrategy { getInput(): Promise; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/client/src/input/VSCodePromptInputStrategy.ts b/client/src/input/VSCodePromptInputStrategy.ts index dd2423e..6ab50ec 100644 --- a/client/src/input/VSCodePromptInputStrategy.ts +++ b/client/src/input/VSCodePromptInputStrategy.ts @@ -8,21 +8,26 @@ export class VSCodePromptInputStrategy implements InputStrategy { promptOptions?: InputBoxOptions, cancelToken?: CancellationToken ) => Thenable - ) {} + ) { } async getInput(): Promise { - while (this.inputQueue.length == 0) { - await this.requestInputFromPrompt(); - } - const character = this.inputQueue.charCodeAt(0); - this.inputQueue = this.inputQueue.substring(1); + while (this.inputQueue.length === 0) { + await this.requestInputFromPrompt(); + } + const character = this.popInputFromQueue(); - return character; + return character; } + private popInputFromQueue() { + const character = this.inputQueue.charCodeAt(0); + this.inputQueue = this.inputQueue.substring(1); + return character; + } + private async requestInputFromPrompt() { - const inputPrompt = await this.requestor({ - prompt: 'More input is required. Please provide input:', - }); - this.inputQueue += inputPrompt; + const inputPrompt = await this.requestor({ + prompt: 'More input is required. Please provide input:', + }); + this.inputQueue += inputPrompt; } } diff --git a/client/src/task/CustomExecutionTerminal.ts b/client/src/task/CustomExecutionTerminal.ts new file mode 100644 index 0000000..c08f57b --- /dev/null +++ b/client/src/task/CustomExecutionTerminal.ts @@ -0,0 +1,74 @@ +import path = require('node:path'); +import * as vscode from 'vscode'; + + +export class CustomExecutionTaskProvider implements vscode.TaskProvider{ + + provideTasks(token?: vscode.CancellationToken): vscode.ProviderResult { + throw new Error('Method not implemented.'); + } + resolveTask(task: vscode.Task, token?: vscode.CancellationToken): vscode.ProviderResult { + const taskDefinition = {}; + throw new Error('5'); + // return new vscode.Task() + } + +} + + +class CustomBuildTaskTerminal implements vscode.Pseudoterminal { + private writeEmitter = new vscode.EventEmitter(); + onDidWrite: vscode.Event = this.writeEmitter.event; + private closeEmitter = new vscode.EventEmitter(); + onDidClose?: vscode.Event = this.closeEmitter.event; + + private fileWatcher: vscode.FileSystemWatcher | undefined; + + constructor(private workspaceRoot: string, private flavor: string, private flags: string[], private getSharedState: () => string | undefined, private setSharedState: (state: string) => void) { + } + + open(initialDimensions: vscode.TerminalDimensions | undefined): void { + // At this point we can start using the terminal. + if (this.flags.indexOf('watch') > -1) { + const pattern = path.join(this.workspaceRoot, 'customBuildFile'); + this.fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); + this.fileWatcher.onDidChange(() => this.doBuild()); + this.fileWatcher.onDidCreate(() => this.doBuild()); + this.fileWatcher.onDidDelete(() => this.doBuild()); + } + this.doBuild(); + } + + close(): void { + // The terminal has been closed. Shutdown the build. + if (this.fileWatcher) { + this.fileWatcher.dispose(); + } + } + + private async doBuild(): Promise { + return new Promise((resolve) => { + this.writeEmitter.fire('Starting build...\r\n'); + let isIncremental = this.flags.indexOf('incremental') > -1; + if (isIncremental) { + if (this.getSharedState()) { + this.writeEmitter.fire('Using last build results: ' + this.getSharedState() + '\r\n'); + } else { + isIncremental = false; + this.writeEmitter.fire('No result from last build. Doing full build.\r\n'); + } + } + + // Since we don't actually build anything in this example set a timeout instead. + setTimeout(() => { + const date = new Date(); + this.setSharedState(date.toTimeString() + ' ' + date.toDateString()); + this.writeEmitter.fire('Build complete.\r\n\r\n'); + if (this.flags.indexOf('watch') === -1) { + this.closeEmitter.fire(0); + resolve(); + } + }, isIncremental ? 1000 : 4000); + }); + } +} \ No newline at end of file diff --git a/server/src/connection.ts b/server/src/connection.ts index 3f45c5c..b40a053 100644 --- a/server/src/connection.ts +++ b/server/src/connection.ts @@ -1,26 +1,30 @@ -import { CompletionItem, CompletionItemKind, Connection, DidChangeConfigurationNotification, DidChangeConfigurationParams, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocumentSyncKind } from 'vscode-languageserver'; +import { CompletionItem, CompletionItemKind, Connection, DidChangeConfigurationNotification, DidChangeConfigurationParams, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver'; +import { validateTextDocument } from './validation'; +import { TextDocument } from 'vscode-languageserver-textdocument'; +import { BranFlakesSettings, defaultSettings, SettingsManager } from './settings'; export class BranFlakesConnectionManager { - hasConfigurationCapability: boolean = false; - hasWorkspaceFolderCapability: boolean = false; - hasDiagnosticRelatedInformationCapability: boolean = false; + - constructor(protected connection: Connection) { + constructor(protected connection: Connection, private validator:typeof validateTextDocument, private documents:TextDocuments, private settingsManager:SettingsManager) { connection.onInitialize(this.initConnection); + connection.onDidChangeConfiguration(this.onDidChangeConfiguration); } + + initConnection(params: InitializeParams) { let capabilities = params.capabilities; // Does the client support the `workspace/configuration` request? // If not, we will fall back using global settings - this.hasConfigurationCapability = !!( + this.settingsManager.hasConfigurationCapability = !!( capabilities.workspace && !!capabilities.workspace.configuration ); - this.hasWorkspaceFolderCapability = !!( + this.settingsManager.hasWorkspaceFolderCapability = !!( capabilities.workspace && !!capabilities.workspace.workspaceFolders ); - this.hasDiagnosticRelatedInformationCapability = !!( + this.settingsManager.hasDiagnosticRelatedInformationCapability = !!( capabilities.textDocument && capabilities.textDocument.publishDiagnostics && capabilities.textDocument.publishDiagnostics.relatedInformation @@ -36,7 +40,7 @@ export class BranFlakesConnectionManager { }, }, }; - if (this.hasWorkspaceFolderCapability) { + if (this.settingsManager.hasWorkspaceFolderCapability) { result.capabilities.workspace = { workspaceFolders: { supported: true, @@ -45,15 +49,31 @@ export class BranFlakesConnectionManager { } return result; } + + onDidChangeConfiguration(change:DidChangeConfigurationParams){ + if (this.settingsManager.hasConfigurationCapability) { + // Reset all cached document settings + this.settingsManager.clearDocumentSettings(); + } else { + this.settingsManager.updateSettings( + (change.settings.languageServerExample || defaultSettings) + ); + } + + // Revalidate all open text documents + Promise.all(this.documents.all().map(validateTextDocument)).catch(e => { + this.connection.console.log('Failed to validate text documents'); + }); + } onInit() { - if (this.hasConfigurationCapability) { + if (this.settingsManager.hasConfigurationCapability) { // Register for all configuration changes. this.connection.client.register( DidChangeConfigurationNotification.type, undefined ); } - if (this.hasWorkspaceFolderCapability) { + if (this.settingsManager.hasWorkspaceFolderCapability) { this.connection.workspace.onDidChangeWorkspaceFolders(_event => { // connection.console.log('Workspace folder change event received.'); }); diff --git a/server/src/server.ts b/server/src/server.ts index 92590c9..a256224 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -9,7 +9,7 @@ import { } from 'vscode-languageserver'; import { TextDocument } from 'vscode-languageserver-textdocument'; -import { BranFlakesSettings, defaultSettings } from './settings'; +import { BranFlakesSettings, defaultSettings, SettingsManager } from './settings'; import { BranFlakesConnectionManager } from './connection'; import { validateTextDocument } from './validation'; @@ -23,29 +23,15 @@ let documents: TextDocuments = new TextDocuments(TextDocument); let hasConfigurationCapability: boolean = false; -let cm = new BranFlakesConnectionManager(connection); let globalSettings: BranFlakesSettings = defaultSettings; // Cache the settings of all open documents let documentSettings: Map> = new Map(); +let settingsManager = new SettingsManager(); +let cm = new BranFlakesConnectionManager(connection, validateTextDocument,documents,settingsManager); -connection.onDidChangeConfiguration(change => { - if (hasConfigurationCapability) { - // Reset all cached document settings - documentSettings.clear(); - } else { - globalSettings = ( - (change.settings.languageServerExample || defaultSettings) - ); - } - - // Revalidate all open text documents - Promise.all(documents.all().map(validateTextDocument)).catch(e => { - connection.console.log('Failed to validate text documents'); - }); -}); export function getDocumentSettings(resource: string): Thenable { if (!hasConfigurationCapability) { @@ -64,7 +50,7 @@ export function getDocumentSettings(resource: string): Thenable { - documentSettings.delete(e.document.uri); + settingsManager.closeDocument(e.document.uri); }); // The content of a text document has changed. This event is emitted diff --git a/server/src/settings.ts b/server/src/settings.ts index 1712d06..6e43a02 100644 --- a/server/src/settings.ts +++ b/server/src/settings.ts @@ -7,7 +7,29 @@ export interface BranFlakesSettings { // The global settings, used when the `workspace/configuration` request is not supported by the client. // Please note that this is not the case when using this server with the client provided in this example // but could happen with other clients. -export const defaultSettings: BranFlakesSettings = { - maxNumberOfProblems: 5 +export const defaultSettings: BranFlakesSettings = { + maxNumberOfProblems: 5 }; + +export class SettingsManager { + hasConfigurationCapability: boolean = false; + hasWorkspaceFolderCapability: boolean = false; + hasDiagnosticRelatedInformationCapability: boolean = false; + + documentSettings: Map> = new Map(); + + #settings = defaultSettings; + + updateSettings(newSettings: BranFlakesSettings) { + this.#settings = newSettings; + } + + closeDocument(doc: string) { + this.documentSettings.delete(doc); + + } + clearDocumentSettings(){ + this.documentSettings.clear(); + } +} \ No newline at end of file diff --git a/server/src/validation.ts b/server/src/validation.ts index 347dacb..f843ec4 100644 --- a/server/src/validation.ts +++ b/server/src/validation.ts @@ -24,6 +24,8 @@ export const validateBrackets = (text: string) => { return [...lp, ...issues]; }; + + export async function validateTextDocument(textDocument: TextDocument): Promise { // In this simple example we get the settings for every validate run. let settings = await getDocumentSettings(textDocument.uri);