diff --git a/src/base-config/keyboard.json b/src/base-config/keyboard.json
index aa9c67cd4d5..07611fea90c 100644
--- a/src/base-config/keyboard.json
+++ b/src/base-config/keyboard.json
@@ -281,6 +281,9 @@
"navigate.gotoDefinition": [
"Ctrl-T"
],
+ "navigate.gotoDefinitionInProject": [
+ "Ctrl-Shift-T"
+ ],
"navigate.jumptoDefinition": [
"Ctrl-J"
],
diff --git a/src/command/Commands.js b/src/command/Commands.js
index dc147eeac6f..e5811dd229c 100644
--- a/src/command/Commands.js
+++ b/src/command/Commands.js
@@ -125,6 +125,7 @@ define(function (require, exports, module) {
exports.NAVIGATE_QUICK_OPEN = "navigate.quickOpen"; // QuickOpen.js doFileSearch()
exports.NAVIGATE_JUMPTO_DEFINITION = "navigate.jumptoDefinition"; // JumpToDefManager.js _doJumpToDef()
exports.NAVIGATE_GOTO_DEFINITION = "navigate.gotoDefinition"; // QuickOpen.js doDefinitionSearch()
+ exports.NAVIGATE_GOTO_DEFINITION_PROJECT = "navigate.gotoDefinitionInProject"; // QuickOpen.js doDefinitionSearchInProject()
exports.NAVIGATE_GOTO_LINE = "navigate.gotoLine"; // QuickOpen.js doGotoLine()
exports.NAVIGATE_GOTO_FIRST_PROBLEM = "navigate.gotoFirstProblem"; // CodeInspection.js handleGotoFirstProblem()
exports.TOGGLE_QUICK_EDIT = "navigate.toggleQuickEdit"; // EditorManager.js _toggleInlineWidget()
diff --git a/src/command/DefaultMenus.js b/src/command/DefaultMenus.js
index 2eb6f871925..912d9eaa306 100644
--- a/src/command/DefaultMenus.js
+++ b/src/command/DefaultMenus.js
@@ -172,6 +172,7 @@ define(function (require, exports, module) {
menu.addMenuItem(Commands.NAVIGATE_QUICK_OPEN);
menu.addMenuItem(Commands.NAVIGATE_GOTO_LINE);
menu.addMenuItem(Commands.NAVIGATE_GOTO_DEFINITION);
+ menu.addMenuItem(Commands.NAVIGATE_GOTO_DEFINITION_PROJECT);
menu.addMenuItem(Commands.NAVIGATE_JUMPTO_DEFINITION);
menu.addMenuItem(Commands.NAVIGATE_GOTO_FIRST_PROBLEM);
menu.addMenuDivider();
diff --git a/src/extensions/default/PhpTooling/PHPSymbolProviders.js b/src/extensions/default/PhpTooling/PHPSymbolProviders.js
new file mode 100644
index 00000000000..8517e1db574
--- /dev/null
+++ b/src/extensions/default/PhpTooling/PHPSymbolProviders.js
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2019 - present Adobe. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*jslint regexp: true */
+
+define(function (require, exports, module) {
+ "use strict";
+
+ var EditorManager = brackets.getModule("editor/EditorManager"),
+ QuickOpen = brackets.getModule("search/QuickOpen"),
+ Commands = brackets.getModule("command/Commands"),
+ CommandManager = brackets.getModule("command/CommandManager"),
+ PathConverters = brackets.getModule("languageTools/PathConverters");
+
+ var SymbolKind = QuickOpen.SymbolKind;
+
+ function convertRangePosToEditorPos(rangePos) {
+ return {
+ line: rangePos.line,
+ ch: rangePos.character
+ };
+ }
+
+ function SymbolInformation(label, fullPath, selectionRange, type, scope, isDocumentSymbolRequest) {
+ this.label = label;
+ this.fullPath = fullPath;
+ this.selectionRange = selectionRange;
+ this.type = type;
+ this.scope = scope;
+ this.isDocumentSymbolRequest = isDocumentSymbolRequest;
+ }
+
+ function createList(list, isDocumentSymbolRequest) {
+ var newlist = [];
+ for (var i = 0; i < list.length; i++) {
+ var symbolInfo = list[i],
+ label = symbolInfo.name,
+ type = SymbolKind[symbolInfo.kind.toString()],
+ fullPath = null,
+ selectionRange = null,
+ scope = symbolInfo.containerName,
+ range = null;
+
+ if (!isDocumentSymbolRequest) {
+ fullPath = PathConverters.uriToPath(symbolInfo.location.uri);
+ } else {
+ if (symbolInfo.selectionRange) {
+ range = symbolInfo.selectionRange;
+ selectionRange = {
+ from: convertRangePosToEditorPos(range.start),
+ to: convertRangePosToEditorPos(range.end)
+ };
+ }
+ }
+
+ if (!selectionRange) {
+ range = symbolInfo.location.range;
+ selectionRange = {
+ from: convertRangePosToEditorPos(range.start),
+ to: convertRangePosToEditorPos(range.end)
+ };
+ }
+
+ newlist.push(new SymbolInformation(label, fullPath, selectionRange, type, scope, isDocumentSymbolRequest));
+ }
+
+ return newlist;
+ }
+
+ function transFormToSymbolList(query, matcher, results, isDocumentSymbolRequest) {
+ var list = createList(results, isDocumentSymbolRequest);
+
+ // Filter and rank how good each match is
+ var filteredList = $.map(list, function (symbolInfo) {
+ var searchResult = matcher.match(symbolInfo.label, query);
+ if (searchResult) {
+ searchResult.symbolInfo = symbolInfo;
+ }
+ return searchResult;
+ });
+
+ // Sort based on ranking & basic alphabetical order
+ QuickOpen.basicMatchSort(filteredList);
+
+ return filteredList;
+ }
+
+ /**
+ * Provider for Document Symbols
+ */
+ function DocumentSymbolsProvider(client) {
+ this.client = client;
+ }
+
+ DocumentSymbolsProvider.prototype.match = function (query) {
+ return query.startsWith("@");
+ };
+
+ DocumentSymbolsProvider.prototype.search = function (query, matcher) {
+ if (!this.client) {
+ return $.Deferred().reject();
+ }
+
+ var serverCapabilities = this.client.getServerCapabilities();
+ if (!serverCapabilities || !serverCapabilities.documentSymbolProvider) {
+ return $.Deferred().reject();
+ }
+
+ var editor = EditorManager.getActiveEditor(),
+ docPath = editor.document.file._path,
+ retval = $.Deferred();
+ query = query.slice(1);
+
+ this.client.requestSymbolsForDocument({
+ filePath: docPath
+ }).done(function (results) {
+ var resultList = transFormToSymbolList(query, matcher, results, true);
+ retval.resolve(resultList);
+ });
+
+ return retval;
+ };
+
+ DocumentSymbolsProvider.prototype.itemFocus = function (selectedItem, query, explicit) {
+ if (!selectedItem || (query.length < 2 && !explicit)) {
+ return;
+ }
+
+ var range = selectedItem.symbolInfo.selectionRange;
+ EditorManager.getCurrentFullEditor().setSelection(range.from, range.to, true);
+ };
+
+ DocumentSymbolsProvider.prototype.itemSelect = function (selectedItem, query) {
+ this.itemFocus(selectedItem, query, true);
+ };
+
+ DocumentSymbolsProvider.prototype.resultsFormatter = function (item, query) {
+ var displayName = QuickOpen.highlightMatch(item);
+ query = query.slice(1);
+
+ if (item.symbolInfo.scope) {
+ return "
" + displayName + " (" + item.symbolInfo.type + ")" + "
" + item.symbolInfo.scope + "";
+ }
+ return "" + displayName + " (" + item.symbolInfo.type + ")" + "";
+ };
+
+ /**
+ * Provider for Project Symbols
+ */
+ function ProjectSymbolsProvider(client) {
+ this.client = client;
+ }
+
+ ProjectSymbolsProvider.prototype.match = function (query) {
+ return query.startsWith("#");
+ };
+
+ ProjectSymbolsProvider.prototype.search = function (query, matcher) {
+ if (!this.client) {
+ return $.Deferred().reject();
+ }
+
+ var serverCapabilities = this.client.getServerCapabilities();
+ if (!serverCapabilities || !serverCapabilities.workspaceSymbolProvider) {
+ return $.Deferred().reject();
+ }
+
+ var retval = $.Deferred();
+ query = query.slice(1);
+
+ this.client.requestSymbolsForWorkspace({
+ query: query
+ }).done(function (results) {
+ var resultList = transFormToSymbolList(query, matcher, results);
+ retval.resolve(resultList);
+ });
+
+ return retval;
+ };
+
+ ProjectSymbolsProvider.prototype.itemFocus = function (selectedItem, query, explicit) {
+ if (!selectedItem || (query.length < 2 && !explicit)) {
+ return;
+ }
+ };
+
+ ProjectSymbolsProvider.prototype.itemSelect = function (selectedItem, query) {
+ var fullPath = selectedItem.symbolInfo.fullPath,
+ range = selectedItem.symbolInfo.selectionRange;
+
+ if (fullPath) {
+ CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, {
+ fullPath: fullPath
+ })
+ .done(function () {
+ if (range.from) {
+ var editor = EditorManager.getCurrentFullEditor();
+ editor.setCursorPos(range.from.line, range.from.ch, true);
+ }
+ });
+ }
+ };
+
+ ProjectSymbolsProvider.prototype.resultsFormatter = function (item, query) {
+ var displayName = QuickOpen.highlightMatch(item);
+ query = query.slice(1);
+
+ if (item.symbolInfo.scope) {
+ return "" + displayName + " (" + item.symbolInfo.type + ")" + "
" + item.symbolInfo.scope + "
" + item.symbolInfo.fullPath + "";
+ }
+ return "" + displayName + " (" + item.symbolInfo.type + ")" + "
" + item.symbolInfo.fullPath + "";
+ };
+
+ exports.SymbolProviders = {
+ DocumentSymbolsProvider: DocumentSymbolsProvider,
+ ProjectSymbolsProvider: ProjectSymbolsProvider
+ };
+});
diff --git a/src/extensions/default/PhpTooling/main.js b/src/extensions/default/PhpTooling/main.js
index d2ecc966bb1..a2de7502d50 100755
--- a/src/extensions/default/PhpTooling/main.js
+++ b/src/extensions/default/PhpTooling/main.js
@@ -30,11 +30,13 @@ define(function (require, exports, module) {
EditorManager = brackets.getModule("editor/EditorManager"),
LanguageManager = brackets.getModule("language/LanguageManager"),
CodeHintManager = brackets.getModule("editor/CodeHintManager"),
+ QuickOpen = brackets.getModule("search/QuickOpen"),
ParameterHintManager = brackets.getModule("features/ParameterHintsManager"),
JumpToDefManager = brackets.getModule("features/JumpToDefManager"),
CodeInspection = brackets.getModule("language/CodeInspection"),
DefaultProviders = brackets.getModule("languageTools/DefaultProviders"),
CodeHintsProvider = require("CodeHintsProvider").CodeHintsProvider,
+ SymbolProviders = require("PHPSymbolProviders").SymbolProviders,
DefaultEventHandlers = brackets.getModule("languageTools/DefaultEventHandlers"),
PreferencesManager = brackets.getModule("preferences/PreferencesManager"),
Strings = brackets.getModule("strings"),
@@ -61,7 +63,9 @@ define(function (require, exports, module) {
chProvider,
phProvider,
lProvider,
- jdProvider;
+ jdProvider,
+ dSymProvider,
+ pSymProvider;
PreferencesManager.definePreference("php", "object", phpConfig, {
description: Strings.DESCRIPTION_PHP_TOOLING_CONFIGURATION
@@ -102,6 +106,8 @@ define(function (require, exports, module) {
phProvider = new DefaultProviders.ParameterHintsProvider(_client),
lProvider = new DefaultProviders.LintingProvider(_client),
jdProvider = new DefaultProviders.JumpToDefProvider(_client);
+ dSymProvider = new SymbolProviders.DocumentSymbolsProvider(_client);
+ pSymProvider = new SymbolProviders.ProjectSymbolsProvider(_client);
JumpToDefManager.registerJumpToDefProvider(jdProvider, ["php"], 0);
CodeHintManager.registerHintProvider(chProvider, ["php"], 0);
@@ -110,6 +116,30 @@ define(function (require, exports, module) {
name: "",
scanFileAsync: lProvider.getInspectionResultsAsync.bind(lProvider)
});
+ //Attach plugin for Document Symbols
+ QuickOpen.addQuickOpenPlugin({
+ name: "PHP Document Symbols",
+ label: Strings.CMD_FIND_DOCUMENT_SYMBOLS + "\u2026",
+ languageIds: ["php"],
+ search: dSymProvider.search.bind(dSymProvider),
+ match: dSymProvider.match.bind(dSymProvider),
+ itemFocus: dSymProvider.itemFocus.bind(dSymProvider),
+ itemSelect: dSymProvider.itemSelect.bind(dSymProvider),
+ resultsFormatter: dSymProvider.resultsFormatter.bind(dSymProvider)
+ });
+ CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION).setEnabled(true);
+ //Attach plugin for Project Symbols
+ QuickOpen.addQuickOpenPlugin({
+ name: "PHP Project Symbols",
+ label: Strings.CMD_FIND_PROJECT_SYMBOLS + "\u2026",
+ languageIds: ["php"],
+ search: pSymProvider.search.bind(pSymProvider),
+ match: pSymProvider.match.bind(pSymProvider),
+ itemFocus: pSymProvider.itemFocus.bind(pSymProvider),
+ itemSelect: pSymProvider.itemSelect.bind(pSymProvider),
+ resultsFormatter: pSymProvider.resultsFormatter.bind(pSymProvider)
+ });
+ CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION_PROJECT).setEnabled(true);
_client.addOnCodeInspection(lProvider.setInspectionResults.bind(lProvider));
}
diff --git a/src/extensions/default/PhpTooling/unittest-files/test/test4.php b/src/extensions/default/PhpTooling/unittest-files/test/test4.php
new file mode 100644
index 00000000000..7caa64749ed
--- /dev/null
+++ b/src/extensions/default/PhpTooling/unittest-files/test/test4.php
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/src/extensions/default/PhpTooling/unittests.js b/src/extensions/default/PhpTooling/unittests.js
index 722acc5b993..3724743b5e7 100644
--- a/src/extensions/default/PhpTooling/unittests.js
+++ b/src/extensions/default/PhpTooling/unittests.js
@@ -27,7 +27,8 @@ define(function (require, exports, module) {
var SpecRunnerUtils = brackets.getModule("spec/SpecRunnerUtils"),
Strings = brackets.getModule("strings"),
FileUtils = brackets.getModule("file/FileUtils"),
- StringUtils = brackets.getModule("utils/StringUtils");
+ StringUtils = brackets.getModule("utils/StringUtils"),
+ StringMatch = brackets.getModule("utils/StringMatch");
var extensionRequire,
phpToolingExtension,
@@ -37,11 +38,13 @@ define(function (require, exports, module) {
CodeInspection,
DefaultProviders,
CodeHintsProvider,
+ SymbolProviders,
EditorManager,
testEditor,
testFolder = FileUtils.getNativeModuleDirectoryPath(module) + "/unittest-files/",
testFile1 = "test1.php",
- testFile2 = "test2.php";
+ testFile2 = "test2.php",
+ testFile4 = "test4.php";
describe("PhpTooling", function () {
@@ -59,8 +62,11 @@ define(function (require, exports, module) {
afterLast(function () {
waitsForDone(phpToolingExtension.getClient().stop(), "stoping php server");
+ testEditor = null;
+ testWindow = null;
+ brackets = null;
+ EditorManager = null;
SpecRunnerUtils.closeTestWindow();
- testWindow = null;
});
@@ -71,6 +77,7 @@ define(function (require, exports, module) {
CodeInspection.toggleEnabled(true);
DefaultProviders = testWindow.brackets.getModule("languageTools/DefaultProviders");
CodeHintsProvider = extensionRequire("CodeHintsProvider");
+ SymbolProviders = extensionRequire("PHPSymbolProviders").SymbolProviders;
});
/**
@@ -316,6 +323,56 @@ define(function (require, exports, module) {
});
}
+ /**
+ * Show the document/project symbols for a language type.
+ *
+ * @param {SymbolProvider} provider The symbol provider to use for the request.
+ * @param {string} query The query string for the request.
+ * @param {Array} expectedSymbols Expected results for the request.
+ */
+ function expectSymbols(provider, query, expectedSymbols) {
+ var requestStatus = null;
+ var request,
+ matcher;
+
+ runs(function () {
+ matcher = new StringMatch.StringMatcher();
+ request = new provider(phpToolingExtension.getClient()).search(query, matcher);
+ request.done(function (status) {
+ requestStatus = status;
+ });
+
+ waitsForDone(request, "Expected Symbols did not resolve", 3000);
+ });
+
+ if (expectedSymbols === []) {
+ expect(requestStatus).toBe([]);
+ return;
+ }
+
+ function matchSymbols(symbols) {
+ var n = symbols.length > 4 ? 4 : symbols.length,
+ i;
+
+ for (i = 0; i < n; i++) {
+ var symbolInfo = symbols[i].symbolInfo;
+ expect(symbolInfo.label).toBe(expectedSymbols[i].label);
+ expect(symbolInfo.type).toBe(expectedSymbols[i].type);
+ expect(symbolInfo.scope).toBe(expectedSymbols[i].scope);
+
+ if (expectedSymbols[i].fullPath === null) {
+ expect(symbolInfo.fullPath).toBe(null);
+ } else {
+ expect(symbolInfo.fullPath.includes(expectedSymbols[i].fullPath)).toBe(true);
+ }
+ }
+
+ }
+ runs(function() {
+ matchSymbols(requestStatus);
+ });
+ }
+
/**
* Trigger a jump to definition, and verify that the editor jumped to
* the expected location. The new location is the variable definition
@@ -495,5 +552,72 @@ define(function (require, exports, module) {
editorJumped({line: 4, ch: 0, file: "test3.php"});
});
});
+
+ it("should fetch document symbols for a given file", function () {
+ waitsForDone(SpecRunnerUtils.openProjectFiles([testFile4]), "open test file: " + testFile4);
+ runs(function () {
+ var provider = SymbolProviders.DocumentSymbolsProvider,
+ query = "@",
+ expectedSymbols = [
+ {
+ "label": "constantValue",
+ "fullPath": null,
+ "type": "Constant",
+ "scope": "MyClass"
+ },
+ {
+ "label": "MyClass",
+ "fullPath": null,
+ "type": "Class",
+ "scope": ""
+ },
+ {
+ "label": "publicFunction",
+ "fullPath": null,
+ "type": "Method",
+ "scope": "MyClass"
+ },
+ {
+ "label": "publicValue",
+ "fullPath": null,
+ "type": "Property",
+ "scope": "MyClass"
+ }
+ ];
+ expectSymbols(provider, query, expectedSymbols);
+ });
+ });
+
+ it("should fetch no document symbols for a given file", function () {
+ waitsForDone(SpecRunnerUtils.openProjectFiles([testFile1]), "open test file: " + testFile1);
+ runs(function () {
+ var provider = SymbolProviders.DocumentSymbolsProvider,
+ query = "@",
+ expectedSymbols = [];
+ expectSymbols(provider, query, expectedSymbols);
+ });
+ });
+
+ it("should fetch project symbols for a given file", function () {
+ runs(function () {
+ var provider = SymbolProviders.ProjectSymbolsProvider,
+ query = "#as",
+ expectedSymbols = [
+ {
+ "label": "MyClass",
+ "fullPath": "test4.php",
+ "type": "Class",
+ "scope": ""
+ },
+ {
+ "label": "TestCase",
+ "fullPath": "test2.php",
+ "type": "Class",
+ "scope": "test"
+ }
+ ];
+ expectSymbols(provider, query, expectedSymbols);
+ });
+ });
});
});
diff --git a/src/languageTools/LanguageClientWrapper.js b/src/languageTools/LanguageClientWrapper.js
index 9cd7a5a42b1..edd9a6b9602 100644
--- a/src/languageTools/LanguageClientWrapper.js
+++ b/src/languageTools/LanguageClientWrapper.js
@@ -110,7 +110,7 @@ define(function (require, exports, module) {
}
case ToolingInfo.FEATURES.PROJECT_SYMBOLS:
{
- if (params && params.query && typeof params.query === "string") {
+ if (hasValidProp(params, "query") && typeof params.query === "string") {
validatedParams = params;
}
break;
diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js
index a3afc09921b..f4874acbd6c 100644
--- a/src/nls/root/strings.js
+++ b/src/nls/root/strings.js
@@ -419,6 +419,7 @@ define({
"CMD_QUICK_OPEN" : "Quick Open",
"CMD_GOTO_LINE" : "Go to Line",
"CMD_GOTO_DEFINITION" : "Quick Find Definition",
+ "CMD_GOTO_DEFINITION_PROJECT" : "Quick Find Definition in Project",
"CMD_GOTO_FIRST_PROBLEM" : "Go to First Problem",
"CMD_TOGGLE_QUICK_EDIT" : "Quick Edit",
"CMD_TOGGLE_QUICK_DOCS" : "Quick Docs",
@@ -888,5 +889,7 @@ define({
"OPEN_PREFERENNCES" : "Open Preferences",
//Strings for LanguageTools Preferences
- "LANGUAGE_TOOLS_PREFERENCES" : "Preferences for Language Tools"
+ "LANGUAGE_TOOLS_PREFERENCES" : "Preferences for Language Tools",
+ "CMD_FIND_DOCUMENT_SYMBOLS" : "Find Document Symbols",
+ "CMD_FIND_PROJECT_SYMBOLS" : "Find Project Symbols"
});
diff --git a/src/search/QuickOpen.js b/src/search/QuickOpen.js
index 5c9f105292f..98336ac40a0 100644
--- a/src/search/QuickOpen.js
+++ b/src/search/QuickOpen.js
@@ -44,8 +44,40 @@ define(function (require, exports, module) {
LanguageManager = require("language/LanguageManager"),
ModalBar = require("widgets/ModalBar").ModalBar,
QuickSearchField = require("search/QuickSearchField").QuickSearchField,
- StringMatch = require("utils/StringMatch");
-
+ StringMatch = require("utils/StringMatch"),
+ ProviderRegistrationHandler = require("features/PriorityBasedRegistration").RegistrationHandler;
+
+ var _providerRegistrationHandler = new ProviderRegistrationHandler(),
+ _registerQuickOpenProvider = _providerRegistrationHandler.registerProvider.bind(_providerRegistrationHandler);
+
+ var SymbolKind = {
+ "1": "File",
+ "2": "Module",
+ "3": "Namespace",
+ "4": "Package",
+ "5": "Class",
+ "6": "Method",
+ "7": "Property",
+ "8": "Field",
+ "9": "Constructor",
+ "10": "Enum",
+ "11": "Interface",
+ "12": "Function",
+ "13": "Variable",
+ "14": "Constant",
+ "15": "String",
+ "16": "Number",
+ "17": "Boolean",
+ "18": "Array",
+ "19": "Object",
+ "20": "Key",
+ "21": "Null",
+ "22": "EnumMember",
+ "23": "Struct",
+ "24": "Event",
+ "25": "Operator",
+ "26": "TypeParameter"
+ };
/**
* The regular expression to check the cursor position
@@ -53,12 +85,6 @@ define(function (require, exports, module) {
*/
var CURSOR_POS_EXP = new RegExp(":([^,]+)?(,(.+)?)?");
- /**
- * List of plugins
- * @type {Array.}
- */
- var plugins = [];
-
/**
* Current plugin
* @type {QuickOpenPlugin}
@@ -77,6 +103,22 @@ define(function (require, exports, module) {
*/
var _curDialog;
+ /**
+ * Helper function to get the plugins based on the type of the current document.
+ * @private
+ * @returns {Array} Returns the plugings based on the languageId of the current document.
+ */
+ function _getPluginsForCurrentContext() {
+ var curDoc = DocumentManager.getCurrentDocument();
+
+ if (curDoc) {
+ var languageId = curDoc.getLanguage().getId();
+ return _providerRegistrationHandler.getProvidersForLanguageId(languageId);
+ }
+
+ return _providerRegistrationHandler.getProvidersForLanguageId(); //plugins registered for all
+ }
+
/**
* Defines API for new QuickOpen plug-ins
*/
@@ -132,18 +174,22 @@ define(function (require, exports, module) {
* cancels Quick Open (via Esc), those changes are automatically reverted.
*/
function addQuickOpenPlugin(pluginDef) {
- plugins.push(new QuickOpenPlugin(
- pluginDef.name,
- pluginDef.languageIds,
- pluginDef.done,
- pluginDef.search,
- pluginDef.match,
- pluginDef.itemFocus,
- pluginDef.itemSelect,
- pluginDef.resultsFormatter,
- pluginDef.matcherOptions,
- pluginDef.label
- ));
+ var quickOpenProvider = new QuickOpenPlugin(
+ pluginDef.name,
+ pluginDef.languageIds,
+ pluginDef.done,
+ pluginDef.search,
+ pluginDef.match,
+ pluginDef.itemFocus,
+ pluginDef.itemSelect,
+ pluginDef.resultsFormatter,
+ pluginDef.matcherOptions,
+ pluginDef.label
+ ),
+ providerLanguageIds = pluginDef.languageIds.length ? pluginDef.languageIds : ["all"],
+ providerPriority = pluginDef.priority || 0;
+
+ _registerQuickOpenProvider(quickOpenProvider, providerLanguageIds, providerPriority);
}
/**
@@ -350,9 +396,10 @@ define(function (require, exports, module) {
this.closePromise = modalBarClosePromise;
this.isOpen = false;
- var i;
+ var i,
+ plugins = _getPluginsForCurrentContext();
for (i = 0; i < plugins.length; i++) {
- var plugin = plugins[i];
+ var plugin = plugins[i].provider;
if (plugin.done) {
plugin.done();
}
@@ -455,17 +502,11 @@ define(function (require, exports, module) {
return { error: null };
}
- // Try to invoke a search plugin
- var curDoc = DocumentManager.getCurrentDocument(), languageId;
- if (curDoc) {
- languageId = curDoc.getLanguage().getId();
- }
-
- var i;
+ var i,
+ plugins = _getPluginsForCurrentContext();
for (i = 0; i < plugins.length; i++) {
- var plugin = plugins[i];
- var languageIdMatch = plugin.languageIds.length === 0 || plugin.languageIds.indexOf(languageId) !== -1;
- if (languageIdMatch && plugin.match(query)) {
+ var plugin = plugins[i].provider;
+ if(plugin.match(query)) {
currentPlugin = plugin;
// Look up the StringMatcher for this plugin.
@@ -613,6 +654,9 @@ define(function (require, exports, module) {
case "@":
dialogLabel = Strings.CMD_GOTO_DEFINITION + "\u2026";
break;
+ case "#":
+ dialogLabel = Strings.CMD_GOTO_DEFINITION_PROJECT + "\u2026";
+ break;
default:
dialogLabel = "";
break;
@@ -732,18 +776,89 @@ define(function (require, exports, module) {
}
}
+ function doDefinitionSearchInProject() {
+ if (DocumentManager.getCurrentDocument()) {
+ beginSearch("#", getCurrentEditorSelectedText());
+ }
+ }
+
+ function _canHandleTrigger(trigger, plugins) {
+ var retval = false;
+
+ plugins.some(function (plugin, index) {
+ var provider = plugin.provider;
+ if (provider.match(trigger)) {
+ retval = true;
+ return true;
+ }
+ });
+
+ return retval;
+ }
+
+ function _setMenuItemStateForLanguage(languageId) {
+ var plugins = _providerRegistrationHandler.getProvidersForLanguageId(languageId);
+ if (_canHandleTrigger("@", plugins)) {
+ CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION).setEnabled(true);
+ } else {
+ CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION).setEnabled(false);
+ }
+
+ if (_canHandleTrigger("#", plugins)) {
+ CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION_PROJECT).setEnabled(true);
+ } else {
+ CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION_PROJECT).setEnabled(false);
+ }
+ }
+
// Listen for a change of project to invalidate our file list
ProjectManager.on("projectOpen", function () {
fileList = null;
});
+ MainViewManager.on("currentFileChange", function (event, newFile, newPaneId, oldFile, oldPaneId) {
+ if (!newFile) {
+ CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION).setEnabled(false);
+ CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION_PROJECT).setEnabled(false);
+ return;
+ }
+
+ var newFilePath = newFile.fullPath,
+ newLanguageId = LanguageManager.getLanguageForPath(newFilePath).getId();
+ _setMenuItemStateForLanguage(newLanguageId);
+
+ DocumentManager.getDocumentForPath(newFilePath)
+ .done(function (newDoc) {
+ newDoc.on("languageChanged.quickFindDefinition", function () {
+ var changedLanguageId = LanguageManager.getLanguageForPath(newDoc.file.fullPath).getId();
+ _setMenuItemStateForLanguage(changedLanguageId);
+ });
+ }).fail(function (err) {
+ console.error(err);
+ });
+
+ if (!oldFile) {
+ return;
+ }
+
+ var oldFilePath = oldFile.fullPath;
+ DocumentManager.getDocumentForPath(oldFilePath)
+ .done(function (oldDoc) {
+ oldDoc.off("languageChanged.quickFindDefinition");
+ }).fail(function (err) {
+ console.error(err);
+ });
+ });
+
CommandManager.register(Strings.CMD_QUICK_OPEN, Commands.NAVIGATE_QUICK_OPEN, doFileSearch);
CommandManager.register(Strings.CMD_GOTO_DEFINITION, Commands.NAVIGATE_GOTO_DEFINITION, doDefinitionSearch);
+ CommandManager.register(Strings.CMD_GOTO_DEFINITION_PROJECT, Commands.NAVIGATE_GOTO_DEFINITION_PROJECT, doDefinitionSearchInProject);
CommandManager.register(Strings.CMD_GOTO_LINE, Commands.NAVIGATE_GOTO_LINE, doGotoLine);
exports.beginSearch = beginSearch;
exports.addQuickOpenPlugin = addQuickOpenPlugin;
exports.highlightMatch = highlightMatch;
+ exports.SymbolKind = SymbolKind;
// Convenience exports for functions that most QuickOpen plugins would need.
exports.stringMatch = StringMatch.stringMatch;