Skip to content
This repository has been archived by the owner on Jul 22, 2019. It is now read-only.

Fixes #142: Move indexing logic entirely to the server-side #143

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,7 @@
"vscode": "^0.11.13"
},
"dependencies": {
"fstream": "^1.0.9",
"mkdirp": "^0.5.1",
"php-parser": "HvyIndustries/php-parser#bde9c58",
"rimraf": "^2.5.2",
"unzip": "^0.1.11",
"open": "^0.0.5",
"vscode-languageclient": "^2.4.2"
}
Expand Down
206 changes: 31 additions & 175 deletions client/src/crane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from 'vscode';
import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient';
import { ThrottledDelayer } from './utils/async';
import { Cranefs } from './utils/Cranefs';
import { Debug } from './utils/Debug';
import { Config } from './utils/Config';

Expand All @@ -22,85 +21,23 @@ const util = require('util');

let craneSettings = workspace.getConfiguration("crane");

const cranefs: Cranefs = new Cranefs();
console.log(process.platform)
export default class Crane
{
public static langClient: LanguageClient;

private disposable: Disposable;
private delayers: { [key: string]: ThrottledDelayer<void> };

public static statusBarItem: StatusBarItem;

constructor(languageClient: LanguageClient) {
Crane.langClient = languageClient;

this.delayers = Object.create(null);

let subscriptions: Disposable[] = [];

workspace.onDidChangeTextDocument((e) => this.onChangeTextHandler(e.document), null, subscriptions);
workspace.onDidCloseTextDocument((textDocument)=> { delete this.delayers[textDocument.uri.toString()]; }, null, subscriptions);
workspace.onDidSaveTextDocument((document) => this.handleFileSave());
console.log("Crane Initialised...");

this.disposable = Disposable.from(...subscriptions);
Crane.langClient = languageClient;

if (!Crane.statusBarItem) {
Crane.statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
Crane.statusBarItem.hide();
}

this.checkVersion().then(indexTriggered => {
this.doInit(indexTriggered);
});
}

private checkVersion(): Thenable<boolean>
{
var self = this;
Debug.info('Checking the current version of Crane');
return new Promise((resolve, reject) => {
cranefs.getVersionFile().then(result => {
if (result.err && result.err.code == "ENOENT") {
// New install
window.showInformationMessage(`Welcome to Crane v${Config.version}.`, "Getting Started Guide").then(data => {
if (data != null) {
open("https://github.com/HvyIndustries/crane/wiki/end-user-guide#getting-started");
}
});
cranefs.createOrUpdateVersionFile(false);
cranefs.deleteAllCaches().then(item => {
self.processAllFilesInWorkspace();
resolve(true);
});
} else {
// Strip newlines from data
result.data = result.data.replace("\n", "");
result.data = result.data.replace("\r", "");
if (result.data && result.data != Config.version) {
// Updated install
window.showInformationMessage(`You're been upgraded to Crane v${Config.version}.`, "View Release Notes").then(data => {
if (data == "View Release Notes") {
open("https://github.com/HvyIndustries/crane/releases");
}
});
cranefs.createOrUpdateVersionFile(true);
cranefs.deleteAllCaches().then(item => {
self.processAllFilesInWorkspace();
resolve(true);
});
} else {
resolve(false);
}
}
});
});
}

public doInit(indexInProgress: boolean) {
console.log("Crane Initialised...");

this.showIndexingStatusBarMessage();

var statusBarItem: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Right);
Expand All @@ -118,7 +55,26 @@ export default class Crane
}
});

var requestType: RequestType<any, any, any> = { method: "workDone" };
var openBrowserMessage: NotificationType<{ url: string }> = { method: "window/openBrowser" };
Crane.langClient.onNotification(openBrowserMessage, message => {
open(message.url);
});

// Update the UI so the user knows the processing status
var fileProcessed: NotificationType<{ filename: string, count: number, total: number, error: any }> = { method: "index/fileProcessed" };
Crane.langClient.onNotification(fileProcessed, data => {
// Get the percent complete
var percent: string = ((data.count / data.total) * 100).toFixed(1);
Crane.statusBarItem.text = `$(zap) Indexing PHP files (${data.count} of ${data.total} / ${percent}%)`;
if (data.error) {
Debug.error("There was a problem parsing PHP file: " + data.filename);
Debug.error(`${data.error}`);
} else {
Debug.info(`Parsed file ${data.count} of ${data.total} : ${data.filename}`);
}
});

var requestType: RequestType<any, any, any> = { method: "index/workDone" };
Crane.langClient.onRequest(requestType, (tree) => {
// this.projectBuilding = false;
Crane.statusBarItem.text = '$(check) PHP File Indexing Complete!';
Expand All @@ -141,37 +97,15 @@ export default class Crane
Debug.info(`Watching these files: {${types.include.join(',')}}`);

var fsw: FileSystemWatcher = workspace.createFileSystemWatcher(`{${types.include.join(',')}}`);
fsw.onDidChange(e => {
workspace.openTextDocument(e).then(document => {
if (document.languageId != 'php') return;
Debug.info('File Changed: ' + e.fsPath);
Crane.langClient.sendRequest({ method: 'buildObjectTreeForDocument' }, {
path: e.fsPath,
text: document.getText()
});
});
});
fsw.onDidCreate(e => {
workspace.openTextDocument(e).then(document => {
if (document.languageId != 'php') return;
Debug.info('File Created: ' + e.fsPath);
Crane.langClient.sendRequest({ method: 'buildObjectTreeForDocument' }, {
path: e.fsPath,
text: document.getText()
});
});
Crane.langClient.notifyFileEvent({ uri: e.fsPath, type: 1});
});
fsw.onDidChange(e => {
Crane.langClient.notifyFileEvent({ uri: e.fsPath, type: 2});
});
fsw.onDidDelete(e => {
Debug.info('File Deleted: ' + e.fsPath);
Crane.langClient.sendRequest({ method: 'deleteFile' }, {
path: e.fsPath
});
Crane.langClient.notifyFileEvent({ uri: e.fsPath, type: 3});
});

if (!indexInProgress) {
// Send request to server to build object tree for all workspace files
this.processAllFilesInWorkspace();
}
}

private showIndexingStatusBarMessage() {
Expand All @@ -184,97 +118,19 @@ export default class Crane
open("https://github.com/HvyIndustries/crane/issues");
}

public handleFileSave() {
var editor = window.activeTextEditor;
if (editor == null) return;

var document = editor.document;

this.buildObjectTreeForDocument(document).then(() => {
Crane.langClient.sendRequest({ method: 'saveTreeCache' }, { projectDir: cranefs.getProjectDir(), projectTree: cranefs.getTreePath() });
}).catch(error => {
Debug.error(util.inspect(error, false, null));
});
}

public processAllFilesInWorkspace() {
cranefs.createProjectDir().then(data => {
var createTreeFile: boolean = false;
// Folder was created so there is no tree cache
if (data.folderCreated) {
this.processWorkspaceFiles();
} else {
// Check for a tree file, if it exists load it;
// otherwise we need to process the files in the workspace
cranefs.doesProjectTreeExist().then(tree => {
if (!tree.exists) {
this.processWorkspaceFiles();
} else {
this.processProject();
}
});
}
}).catch(error => {
Debug.error(util.inspect(error, false, null));
});
}


public deleteCaches() {
var self = this;
cranefs.deleteAllCaches().then(success => {
window.showInformationMessage('All PHP file caches were successfully deleted');
self.processAllFilesInWorkspace();
});
Crane.langClient.sendRequest({ method: "index/deleteAllCaches" }, {});
}

public rebuildProject() {
cranefs.rebuildProject();
Crane.langClient.sendRequest({ method: "index/rebuild" }, {});
}

public downloadPHPLibraries() {
cranefs.downloadPHPLibraries();
}

public processWorkspaceFiles() {
cranefs.processWorkspaceFiles();
}

public processProject() {
cranefs.processProject();
}

private onChangeTextHandler(textDocument: TextDocument) {
// Only parse PHP files
if (textDocument.languageId != "php") return;

let key = textDocument.uri.toString();
let delayer = this.delayers[key];

if (!delayer) {
delayer = new ThrottledDelayer<void>(250);
this.delayers[key] = delayer;
}

delayer.trigger(() => this.buildObjectTreeForDocument(textDocument));
}

private buildObjectTreeForDocument(document: TextDocument): Promise<void>
{
return new Promise<void>((resolve, reject) => {
var path = document.fileName;
var text = document.getText();
var projectDir = cranefs.getProjectDir();
var projectTree = cranefs.getTreePath();

var requestType: RequestType<any, any, any> = { method: "buildObjectTreeForDocument" };
Crane.langClient.sendRequest(requestType, { path, text, projectDir, projectTree }).then(() => resolve() );
});
Crane.langClient.sendRequest({ method: "index/downloadStubs" }, { url: Config.phpstubsZipFile });
}

dispose()
{
this.disposable.dispose();
dispose() {
Crane.statusBarItem.dispose();
}
}
3 changes: 3 additions & 0 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export function activate(context: ExtensionContext)
synchronize: {
configurationSection: "languageServerExample",
fileEvents: workspace.createFileSystemWatcher("**/.clientrc")
},
initializationOptions: {
enableCache: Config.enableCache
}
}

Expand Down
Loading