'use strict'; // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below const vscode = require('vscode'); const phpFunctionSuggestions_1 = require('./phpFunctionSuggestions'); exports.phpFileFunctions = {}; exports.phpFileStaticFunctions = {}; exports.phpFileUses = {}; exports.PHP_MODE = { language: 'php', scheme: 'file' }; // this method is called when your extension is activated // your extension is activated the very first time the command is executed function activate(context) { // Do the initial indexing indexPhpFiles(); console.log(exports.phpFileFunctions); console.log(Object.keys(exports.phpFileUses)); vscode.workspace.onDidSaveTextDocument(function(document) { indexPhpFiles(); }); // Setup our class as a compvarion item provider for function autocompvare context.subscriptions.push(vscode.languages.registerCompletionItemProvider(exports.PHP_MODE, { provideCompletionItems(document, position, token) { var filename = document.fileName; var lineText = document.lineAt(position.line).text; var lineTillCurrentPosition = lineText.substr(0, position.character); var wordAtPosition = document.getWordRangeAtPosition(position); var currentWord = ''; if (wordAtPosition && wordAtPosition.start.character < position.character) { var word = document.getText(wordAtPosition); currentWord = word.substr(0, position.character - wordAtPosition.start.character); } var clas = /new\s+(\\)?(\w+)(\\\w+)*/.exec(lineText); var use = /use\s+(\w+)(\\\w+)*/.exec(lineText); var execute = /->(\w+)/.exec(lineText); var executeStatic = /::(\w+)/.exec(lineText); // Check through the list of functions that are included in this file and see if any match // the starting varter of the word we have so far var suggestions = []; // Check what files the current document includes/requires var currentFileName = document.uri.fsPath.replace(vscode.workspace.rootPath, '').slice(1); var currentPath = document.uri.fsPath.replace(vscode.workspace.rootPath, '').replace("src/", ""); // Look through all included/required files for the current document for (var f in exports.phpFileFunctions) { // Checking normal functions if (execute) for (var func in exports.phpFileFunctions[f]) { func = exports.phpFileFunctions[f][func]; if (func.function.indexOf(currentWord) > 0 && execute[1] == currentWord && (func.functionModifiers["public"] || f == currentPath)) { var newSuggestion = new vscode.CompletionItem(func.function, vscode.CompletionItemKind.Function); params = func.params; var parameters = []; params.forEach(function(value, key) { if (value) { params[key] = "$" + value[1]; parameters[key] = (typeof value[2] !== "undefined" ? value[2] + " " : "") + value[1]; parameters[key] += typeof value[3] !== "undefined" ? " = " + value[3] : ""; } }); newSuggestion.insertText = func.function+"(" + params.join(", ") + ")"; newSuggestion.documentation = func.comment; newSuggestion.detail = "(" + parameters.join(", ") + ")"; suggestions.push(newSuggestion); } }; // Checking static functions if (executeStatic) for (var func in exports.phpFileStaticFunctions[f]) { func = exports.phpFileStaticFunctions[f][func]; if (func.function.indexOf(currentWord) > 0 && executeStatic[1] == currentWord) { var newSuggestion = new vscode.CompletionItem(func.function, vscode.CompletionItemKind.Function); var params = func.params; var parameters = []; params.forEach(function(value, key) { if (value) { params[key] = "$" + value[1]; parameters[key] = (typeof value[2] !== "undefined" ? value[2] + " " : "") + value[1]; parameters[key] += typeof value[3] !== "undefined" ? " = " + value[3] : ""; } }) newSuggestion.insertText = func.function+"(" + params.join(", ") + ")"; newSuggestion.documentation = func.comment; newSuggestion.detail = "(" + parameters.join(", ") + ")"; suggestions.push(newSuggestion); } }; if (f.indexOf(currentWord) > 0) { if (clas && (clas[2] == currentWord || clas[3] == "\\" + currentWord)) { // New instance var currentClass = f.substr(0, f.length - 4).replace(new RegExp("\/", "g"), "\\"); var params = []; if (typeof exports.phpFileFunctions[f]["__construct"] !== "undefined") { params = exports.phpFileFunctions[f]["__construct"].params; } params.forEach(function(value, key) { if (value) params[key] = "$" + value[1]; }); if (currentClass.startsWith("\\")) currentClass = currentClass.substr(1); var newSuggestion = new vscode.CompletionItem(currentClass, vscode.CompletionItemKind.Class); if (typeof clas[1] == "undefined" && typeof exports.phpFileUses[currentPath] !== "undefined" && typeof exports.phpFileUses[currentPath][currentClass] !== "undefined") { newSuggestion.insertText = currentClass.split("\\")[currentClass.split("\\").length - 1] + "(" + params.join(", ") + ");"; } else { newSuggestion.insertText = "\\" + currentClass + "(" + params.join(", ") + ");"; } newSuggestion.detail = "Class " + currentClass; suggestions.push(newSuggestion); } else if (use && (use[1] == currentWord || use[2] == "\\" + currentWord)) { // Use var currentClass = f.substr(0, f.length - 4); currentClass = currentClass.replace(new RegExp("\/", "g"), "\\"); if (currentClass.startsWith("\\")) currentClass = currentClass.substr(1); var newSuggestion = new vscode.CompletionItem(currentClass, vscode.CompletionItemKind.Class); newSuggestion.detail = "Class " + currentClass; newSuggestion.insertText = currentClass + ";\n"; suggestions.push(newSuggestion); } else if (!(execute && execute[1] == currentWord) && !(executeStatic && executeStatic[1] == currentWord)) { // static classes var currentClass = f.substr(0, f.length - 4); currentClass = currentClass.replace(new RegExp("\/", "g"), "\\"); if (currentClass.startsWith("\\")) currentClass = currentClass.substr(1); var newSuggestion = new vscode.CompletionItem(currentClass, vscode.CompletionItemKind.Class); newSuggestion.detail = "Class " + currentClass; if (typeof exports.phpFileUses[currentPath] !== "undefined" && typeof exports.phpFileUses[currentPath][currentClass] !== "undefined") { newSuggestion.insertText = currentClass.split("\\")[currentClass.split("\\").length - 1] + "::"; } else { newSuggestion.insertText = "\\" + currentClass + "::"; } suggestions.push(newSuggestion); } } }; return suggestions; } })); // Setup our plugin to help with function signatures context.subscriptions.push(vscode.languages.registerSignatureHelpProvider(exports.PHP_MODE, new phpFunctionSuggestions_1.PhpSignatureHelpProvider(vscode.workspace.getConfiguration('php')['docsTool']), '(', ',')); // The command has been defined in the package.json file // Now provide the implementation of the command with registerCommand // The commandId parameter must match the command field in package.json var indexDisposable = vscode.commands.registerCommand('pmide.indexPhpFiles', () => { // The code you place here will be executed every time your command is executed indexPhpFiles(); }); var printDisposable = vscode.commands.registerCommand('pmide.printPhpFiles', () => { console.log(Object.keys(exports.phpFileFunctions).length); console.log(exports.phpFileUses); }); context.subscriptions.push(indexDisposable); context.subscriptions.push(printDisposable); } exports.activate = activate; // this method is called when your extension is deactivated function deactivate() {} exports.deactivate = deactivate; // Function to handle the indexing of PHP files function indexPhpFiles() { // Clear out the cached data exports.phpFileUses = {}; exports.phpFileFunctions = {}; var indexResult = vscode.workspace.findFiles("**/*.php", "", 1000).then(function(list) { if (list) { var p = new Promise(function(resolve, reject) { list.forEach((phpFile) => { var path = phpFile.fsPath; var fileName = path.replace(vscode.workspace.rootPath, "").replace("src/", "").slice(1); if (!(fileName in exports.phpFileFunctions)) { exports.phpFileFunctions[fileName] = []; } if (!(fileName in exports.phpFileStaticFunctions)) { exports.phpFileStaticFunctions[fileName] = []; } // Read through the PHP file for includes/requires and function definitions var read = require('fs').readFileSync(path, 'utf8'); var lineReader = read.split("\n"); try { lineReader.forEach(function(line) { // Thats a bit messy for this one so: $2 = optionnal description comment, $4 = functions specifications (static, public, abstract, final,...), $7 = function name, $8 = arguments, $14 = return of function var functionRegex = /(\/\*\*?((\s|.|\n)+)\*\/)?\s*(((abstract|public|protected|private|final|static)\s*)*)function\s+(\w+)\(((\s*\w+)?\s*\$\w+\s*(,(\s*\w+)?\s*\$\w+\s*)*\s*)?\)\s*(:\s*(\w+)\s*)?({|;)/mig var match = functionRegex.exec(line); if (match) { // Matching function modifiers var functionModifiersLitteral = match[4].replace(/\s/, " ").split(" "); var functionModifiers = { "abstract": false, "public": false, "protected": false, "private": false, "final": false, "static": false }; functionModifiersLitteral.forEach(function(modifier) { functionModifiers[modifier] = true; }) var comment = typeof match[3] !== "undefined" ? match[3].replace(/[*]/gim, "") : "From " + fileName; // Parameters var params = []; if (typeof match[8] !== "undefined") match[8].replace(/\s*,\s*/, ",").split(",").forEach(function(m) { var paramers = /((\w+)\s+)?(\$\w+)(\s*\=[^,)]+)?/.exec(m) if (typeof paramers !== "undefined" && paramers !== null) params.push([paramers[0], paramers[3], paramers[2], paramers[5]]); // Later use of knowning which equals to what. }); // Exporting function if (!functionModifiers.static) { exports.phpFileFunctions[fileName][match[7]] = { function: match[7], params: params, functionModifiers: functionModifiers, comment: comment }; } else { exports.phpFileStaticFunctions[fileName][match[7]] = { function: match[7], params: params, functionModifiers: functionModifiers, comment: comment }; } } // Check for uses var includeRegex = /use\s+((\w+\\)*)(\w+)(\s+as\s+(\w+)\s*)?;/; match = includeRegex.exec(line); if (match) { if (!(fileName in exports.phpFileUses)) { exports.phpFileUses[fileName] = []; } // Check if there is a match of "as" to set it. var classType = ''; if (typeof match[4] !== "undefined") { classType = match[5]; } else { classType = match[3]; } exports.phpFileUses[fileName][match[1] + match[3]] = classType; } }); } catch (e) { console.error(e); } }); }) } else { console.log("No workspace defined"); } }, function(reason) { console.log("Error: " + reason); }); // Libraries if (require('fs').existsSync(vscode.workspace.getConfiguration('php')['pocketMinePath'])) { var libraryResult = require("child_process").execSync("find " + vscode.workspace.getConfiguration('php')['pocketMinePath'] + " -maxdepth 10 -type f | fgrep .php").toString().split("\n"); if (libraryResult) { libraryResult.forEach(function(path) { if (require('fs').existsSync(path)) { var fileName = path.replace(vscode.workspace.getConfiguration('php')['pocketMinePath'], "").slice(1); if (!(fileName in exports.phpFileFunctions)) { exports.phpFileFunctions[fileName] = {}; } if (!(fileName in exports.phpFileStaticFunctions)) { exports.phpFileStaticFunctions[fileName] = []; } // Read through the PHP file for includes/requires and function definitions var read = require('fs').readFileSync(path, 'utf8'); try { var lineReader = read.split("\n"); lineReader.forEach(function(line) { // Thats a bit messy for this one so: $2 = optionnal description comment, $4 = functions specifications (static, public, abstract, final,...), $7 = function name, $8 = arguments, $14 = return of function var functionRegex = /(\/\*\*?((\s|.|\n)+)\*\/)?\s*(((abstract|public|protected|private|final|static)\s*)*)function\s+(\w+)\(((\s*\w+)?\s*\$\w+\s*(,(\s*\w+)?\s*\$\w+\s*)*\s*)?\)\s*(:\s*(\w+)\s*)?({|;)/mig var match = functionRegex.exec(line); if (match) { // Matching function modifiers var functionModifiersLitteral = match[4].replace(/\s/, " ").split(" "); var functionModifiers = { "abstract": false, "public": false, "protected": false, "private": false, "final": false, "static": false }; functionModifiersLitteral.forEach(function(modifier) { functionModifiers[modifier] = true; }) var comment = typeof match[3] !== "undefined" ? match[3].replace(/[*]/gim, "") : "From " + fileName; // Parameters var params = []; if (typeof match[8] !== "undefined") match[8].replace(/\s*,\s*/, ",").split(",").forEach(function(m) { var paramers = /((\w+)\s+)?(\$\w+)(\s*\=[^,)]+)?/.exec(m) if (typeof paramers !== "undefined" && paramers !== null) params.push([paramers[0], paramers[3], paramers[2], paramers[5]]); // Later use of knowning which equals to what. }); // Exporting function if (!functionModifiers.static) { exports.phpFileFunctions[fileName][match[7]] = { function: match[7], params: params, functionModifiers: functionModifiers, comment: comment }; } else { exports.phpFileStaticFunctions[fileName][match[7]] = { function: match[7], params: params, functionModifiers: functionModifiers, comment: comment }; } } }); } catch (err) { console.error(err); // Fails silently later } } }); } else { console.log("No workspace defined"); } } } //# sourceMappingURL=extension.js.map