Skip to content

Commit

Permalink
Refactored and improved handling of GSC file changes, renaming, movin…
Browse files Browse the repository at this point in the history
…g; refactored events
  • Loading branch information
eyza-cod2 committed Oct 16, 2024
1 parent daacd3c commit 14cc809
Show file tree
Hide file tree
Showing 23 changed files with 1,177 additions and 442 deletions.
162 changes: 162 additions & 0 deletions src/Events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import * as vscode from 'vscode';
import { GscConfig } from './GscConfig';
import { GscFiles } from './GscFiles';
import { GscStatusBar } from './GscStatusBar';
import { GscFile } from './GscFile';
import { LoggerOutput } from './LoggerOutput';
import { Issues } from './Issues';

export class Events {

static activate(context: vscode.ExtensionContext) {


// An event that is emitted when the configuration changed.
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(async (e) => {
try {
LoggerOutput.log("[Events] Configuration changed.");

await GscConfig.onDidChangeConfiguration(e);

} catch (error) {
Issues.handleError(error);
}
}));


// An event that is emitted when a workspace folder is added or removed.
//**Note:** this event will not fire if the first workspace folder is added, removed or changed,
// because in that case the currently executing extensions (including the one that listens to this
// event) will be terminated and restarted so that the (deprecated) `rootPath` property is updated
// to point to the first workspace folder.
context.subscriptions.push(vscode.workspace.onDidChangeWorkspaceFolders(async e => {
try {
LoggerOutput.log("[Events] Workspace folders changed.");

await GscFiles.onChangeWorkspaceFolders(e);

} catch (error) {
Issues.handleError(error);
}
}));


var debouncedTimerOnDidChangeActiveTextEditor: NodeJS.Timeout | undefined = undefined;
// An event which fires when the window.activeTextEditor active editor has changed.
// *Note* that the event also fires when the active editor changes to `undefined`.
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(async (e) => {
try {
const uri = e?.document.uri;
const uriStr = uri ? vscode.workspace.asRelativePath(uri) : "undefined";

LoggerOutput.log("[Events] Active editor changed to " + uriStr + ", debouncing update...");

// Debounce the update
if (debouncedTimerOnDidChangeActiveTextEditor) {
clearTimeout(debouncedTimerOnDidChangeActiveTextEditor);
}
debouncedTimerOnDidChangeActiveTextEditor = setTimeout(async () => {
debouncedTimerOnDidChangeActiveTextEditor = undefined;

LoggerOutput.log("[Events] Debounce done (250ms) - Active editor changed to " + e?.document.fileName);

await GscStatusBar.updateStatusBar("activeEditorChanged");
}, 250);

} catch (error) {
Issues.handleError(error);
}
}));


// An event that is emitted when a text document is changed. This usually happens
// when the contents changes but also when other things like the dirty-state changes.
vscode.workspace.onDidChangeTextDocument(e => {
try {
//LoggerOutput.log("[Events] Text document changed.");

GscFiles.onTextDocumentChange(e);
} catch (error) {
Issues.handleError(error);
}
}, this, context.subscriptions);



// An event which fires when the selection in an editor has changed.
context.subscriptions.push(vscode.window.onDidChangeTextEditorSelection(e => {
try {
//LoggerOutput.log("[Events] Editor selection changed.");

GscFiles.onChangeEditorSelection(e);
} catch (error) {
Issues.handleError(error);
}
}));


// File rename
context.subscriptions.push(vscode.workspace.onDidRenameFiles(async e => {
try {
LoggerOutput.log("[Events] File has been renamed. " + e.files.map(f => vscode.workspace.asRelativePath(f.oldUri) + " -> " + vscode.workspace.asRelativePath(f.newUri)).join(", "));

} catch (error) {
Issues.handleError(error);
}
}));

// File delete
context.subscriptions.push(vscode.workspace.onDidDeleteFiles(async e => {
try {
LoggerOutput.log("[Events] File has been deleted. " + e.files.map(f => vscode.workspace.asRelativePath(f)).join(", "));

} catch (error) {
Issues.handleError(error);
}
}));

// File create
context.subscriptions.push(vscode.workspace.onDidCreateFiles(async e => {
try {
LoggerOutput.log("[Events] File has been created. " + e.files.map(f => vscode.workspace.asRelativePath(f)).join(", "));

} catch (error) {
Issues.handleError(error);
}
}));
}





private static readonly onDidGscFileParsedEvent = new vscode.EventEmitter<GscFile>();
public static readonly onDidGscFileParsed = this.onDidGscFileParsedEvent.event;


static GscFileParsed(gscFile: GscFile) {
LoggerOutput.log("[Events] GSC file parsed", vscode.workspace.asRelativePath(gscFile.uri));

this.onDidGscFileParsedEvent.fire(gscFile);
}






private static readonly onDidGscDiagnosticChangeEvent = new vscode.EventEmitter<GscFile>();
public static readonly onDidGscDiagnosticChange = this.onDidGscDiagnosticChangeEvent.event;

public static GscDiagnosticsHasChanged(gscFile: GscFile) {
LoggerOutput.log("[Events] GSC diagnostics changed for file", vscode.workspace.asRelativePath(gscFile.uri));

this.onDidGscDiagnosticChangeEvent.fire(gscFile);
}


static GscFileCacheFileHasChanged(fileUri: vscode.Uri) {
LoggerOutput.log("[Events] GSC cache changed for file", vscode.workspace.asRelativePath(fileUri));

}
}
15 changes: 7 additions & 8 deletions src/Gsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,35 @@ import { GscStatusBar } from './GscStatusBar';
import { GscConfig } from './GscConfig';
import { GscCodeActionProvider } from './GscCodeActionProvider';
import { Issues } from './Issues';
import { LoggerOutput } from './LoggerOutput';


export class Gsc {

static async activate(context: vscode.ExtensionContext) {

console.log("------------------------------------------------------------");
console.log("- GSC extension activated -");
console.log("------------------------------------------------------------");
console.log("##### GSC extension activated #####");
LoggerOutput.log("[Gsc] Extension activated");

// Register events
try {
await GscConfig.activate(context);
await GscStatusBar.activate(context);
await GscFiles.activate(context);
await GscDiagnosticsCollection.activate(context);
await GscFiles.activate(context);
await GscCodeActionProvider.activate(context);
await GscSemanticTokensProvider.activate(context);
await GscCompletionItemProvider.activate(context);
await GscDefinitionProvider.activate(context);
await GscHoverProvider.activate(context);
await GscStatusBar.activate(context);
} catch (error) {
Issues.handleError(error);
}
}

static deactivate() {
console.log("------------------------------------------------------------");
console.log("- GSC extension deactivated -");
console.log("------------------------------------------------------------");
console.log("##### GSC extension deactivated #####");
LoggerOutput.log("[Gsc] Extension deactivating");

GscFiles.deactivate();
}
Expand Down
5 changes: 4 additions & 1 deletion src/GscCodeActionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import * as vscode from 'vscode';
import { ConfigErrorDiagnostics, GscConfig } from './GscConfig';
import * as path from 'path';
import { Issues } from './Issues';
import { LoggerOutput } from './LoggerOutput';

export class GscCodeActionProvider implements vscode.CodeActionProvider {

static async activate(context: vscode.ExtensionContext) {
static async activate(context: vscode.ExtensionContext) {
LoggerOutput.log("[GscCodeActionProvider] Activating");

vscode.languages.registerCodeActionsProvider('gsc', new GscCodeActionProvider(), {
providedCodeActionKinds: [vscode.CodeActionKind.QuickFix]
});
Expand Down
13 changes: 8 additions & 5 deletions src/GscCompletionItemProvider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as vscode from 'vscode';
import { GscFile, GscFiles } from './GscFiles';
import { GroupType, GscData, GscGroup, GscVariableDefinitionType } from './GscFileParser';
import { GscFiles } from './GscFiles';
import { GscFile } from './GscFile';
import { GroupType, GscGroup, GscVariableDefinitionType } from './GscFileParser';
import { CodFunctions } from './CodFunctions';
import { GscConfig, GscGame } from './GscConfig';
import { GscFunctions, GscVariableDefinition } from './GscFunctions';
Expand All @@ -17,7 +18,9 @@ export interface CompletionConfig {

export class GscCompletionItemProvider implements vscode.CompletionItemProvider {

static async activate(context: vscode.ExtensionContext) {
static async activate(context: vscode.ExtensionContext) {
LoggerOutput.log("[GscCompletionItemProvider] Activating");

context.subscriptions.push(vscode.languages.registerCompletionItemProvider('gsc', new GscCompletionItemProvider(), '\\', '.', '[', ']'));
}

Expand All @@ -28,9 +31,9 @@ export class GscCompletionItemProvider implements vscode.CompletionItemProvider
// This function is called when user types a character or presses ctrl+space

// Get parsed file
const gscFile = await GscFiles.getFileData(document.uri);
const gscFile = await GscFiles.getFileData(document.uri, true, "provide completion items");

const currentGame = GscConfig.getSelectedGame(document.uri);
const currentGame = gscFile.config.currentGame;

const items = await GscCompletionItemProvider.getCompletionItems(gscFile, position, currentGame, undefined, document.uri);

Expand Down
46 changes: 16 additions & 30 deletions src/GscConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import * as vscode from 'vscode';
import { LoggerOutput } from './LoggerOutput';
import { GscDiagnosticsCollection } from './GscDiagnosticsCollection';
import { GscFiles } from './GscFiles';
import { GscStatusBar } from './GscStatusBar';
import { Issues } from './Issues';

// These must match with package.json settings
Expand Down Expand Up @@ -106,47 +109,30 @@ export class GscConfig {


static async activate(context: vscode.ExtensionContext) {
vscode.workspace.onDidChangeConfiguration((e) => this.onDidChangeConfiguration(e), null, context.subscriptions);
LoggerOutput.log("[GscConfig] Activating");
}


/**
* Handle vscode configuration change event.
* Emit a configuration change event. This will call all subscribers in the order they were added.
*/
private static async onDidChangeConfiguration(e: vscode.ConfigurationChangeEvent) {
public static async onDidChangeConfiguration(e: vscode.ConfigurationChangeEvent) {
if (e.affectsConfiguration('gsc')) {
LoggerOutput.log("[GscConfig] GSC configuration changed.");

for (const handler of this.configChangeSubscribers) {
try {
const result = handler();
if (result instanceof Promise) {
await result;
}
} catch (error) {
Issues.handleError(error);
}
}
}
}

// 1. Load new configuration for each workspace and assign it to cached files
GscFiles.updateConfigurationOfCachedFiles();

/**
* Subscribe to configuration changes. The handler will be called whenever the configuration changes. Subscribers are called in the order they were added.
* @param handler
*/
public static onDidConfigChange(handler: ConfigChangeHandler): vscode.Disposable {
this.configChangeSubscribers.push(handler);
return vscode.Disposable.from({
dispose: () => {
const index = this.configChangeSubscribers.indexOf(handler);
if (index > -1) {
this.configChangeSubscribers.splice(index, 1);
}
}
});
}
// 2. Update tree view

// 3. Update status bar in case the game has changed
await GscStatusBar.updateStatusBar("configChanged");

// 4. Update diagnostics for all files with new configuration
await GscDiagnosticsCollection.updateDiagnosticsForAll("config changed");
}
}



Expand Down
10 changes: 7 additions & 3 deletions src/GscDefinitionProvider.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import * as vscode from 'vscode';
import { GscFile, GscFiles } from './GscFiles';
import { GroupType, GscData, GscFileParser } from './GscFileParser';
import { GscFiles } from './GscFiles';
import { GscFile } from './GscFile';
import { GroupType } from './GscFileParser';
import { GscFunctions } from './GscFunctions';
import { Issues } from './Issues';
import { LoggerOutput } from './LoggerOutput';

export class GscDefinitionProvider implements vscode.DefinitionProvider {

static async activate(context: vscode.ExtensionContext) {
LoggerOutput.log("[GscDefinitionProvider] Activating");

context.subscriptions.push(vscode.languages.registerDefinitionProvider('gsc', new GscDefinitionProvider()));
}

Expand All @@ -18,7 +22,7 @@ export class GscDefinitionProvider implements vscode.DefinitionProvider {
{
try {
// Get parsed file
const gscFile = await GscFiles.getFileData(document.uri);
const gscFile = await GscFiles.getFileData(document.uri, false, "provide definition");

const locations = await GscDefinitionProvider.getFunctionDefinitionLocations(gscFile, position);

Expand Down
Loading

0 comments on commit 14cc809

Please sign in to comment.