Commit 6b6f651e authored by Eugene Ostroukhov's avatar Eugene Ostroukhov Committed by Commit Bot

DevTools: Introduce a search module

Introduces a search module with an extensible search view.

R=dgozman, pfeldman

Bug: 468416
Change-Id: I2fcb0d527d1e3ceab785712a234851a9274949af
Reviewed-on: https://chromium-review.googlesource.com/929893
Commit-Queue: Eugene Ostroukhov <eostroukhov@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#539187}
parent 6ff03373
......@@ -20,10 +20,9 @@
function step2() {
panel.searchableView().showSearchField();
TestRunner.addResult('Search controller: \'' + panel.searchableView()._searchInputElement.value + '\'');
var action = new Sources.AdvancedSearchView.ActionDelegate();
var action = new Search.SearchView.ActionDelegate();
action._showSearch();
var searchView =
/** @type {!Sources.AdvancedSearchView} */ (self.runtime.sharedInstance(Sources.AdvancedSearchView));
var searchView = /** @type {!Search.SearchView} */ (self.runtime.sharedInstance(Search.SearchView));
TestRunner.addResult('Advanced search controller: \'' + searchView._search.value + '\'');
TestRunner.completeTest();
}
......
......@@ -9,6 +9,7 @@ Loaded modules:
inline_editor
object_ui
quick_open
search
snippets
source_frame
sources
......
......@@ -35,7 +35,7 @@
]);
function dumpSearchResults(next) {
var searchConfig = new Workspace.SearchConfig('window.foo f:foo', true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', 'window.foo f:foo', true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
}
......
Verify that search doesn't search in binary resources.
Search result #1: uiSourceCode.url = http://127.0.0.1:8000/devtools/search/search-ignore-binary-files.js
search match #1: lineNumber = 17, lineContent = ' var searchConfig = new Workspace.SearchConfig('AAAAAAA', true, false);'
search match #1: lineNumber = 17, lineContent = ' var searchConfig = new Search.SearchConfig('sources.search-in-files', 'AAAAAAA', true, false);'
......@@ -15,7 +15,7 @@
function doSearch(next) {
var scope = new Sources.SourcesSearchScope();
var searchConfig = new Workspace.SearchConfig('AAAAAAA', true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', 'AAAAAAA', true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, TestRunner.completeTest.bind(TestRunner));
}
})();
......@@ -19,12 +19,12 @@
var query = 'color: blue';
TestRunner.addResult('\nSearching for: "' + query + '"');
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
await new Promise(x => SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, x));
var query = 'window.foo';
TestRunner.addResult('\nSearching for: "' + query + '"');
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
await new Promise(x => SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, x));
TestRunner.completeTest();
......
......@@ -32,7 +32,7 @@
}
function onAllResourcesLoaded() {
UI.viewManager.showView('sources.search');
UI.viewManager.showView('search.search');
fs.reportCreated(fileSystemCreated);
function fileSystemCreated() {
......@@ -66,14 +66,14 @@
function testIgnoreCase(next) {
var query = 'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
function testCaseSensitive(next) {
var query = 'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, false, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, false, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -81,7 +81,7 @@
var query = 'searchTest' +
'UniqueString' +
' file:html';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -89,7 +89,7 @@
var query = 'file:js ' +
'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -98,7 +98,7 @@
'searchTest' +
'UniqueString' +
' file:html';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -107,7 +107,7 @@
'Unique' +
' space' +
' String';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -117,7 +117,7 @@
'Unique' +
' space' +
' String';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -128,7 +128,7 @@
' space' +
' String' +
' file:search';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -139,7 +139,7 @@
' space' +
' String' +
' file:search file:html';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -149,7 +149,7 @@
' file:html ' +
' space' +
' String';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -160,7 +160,7 @@
' space' +
' String' +
' file:search';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -172,7 +172,7 @@
' space' +
' String' +
' file:search';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -180,7 +180,7 @@
var query = 'searchTest' +
'UniqueString' +
' file:search -file:js -file:css';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -190,7 +190,7 @@
' -file:css ' +
' space' +
' String';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -199,7 +199,7 @@
var query = 'searchTest' +
'Unique' +
' file:www';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, step2);
function step2() {
......@@ -207,7 +207,7 @@
query = 'searchTest' +
'Unique' +
' file:zzz';
searchConfig = new Workspace.SearchConfig(query, true, false);
searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
}
},
......@@ -229,7 +229,7 @@
' BAR');
var query = 'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
}
];
......
......@@ -41,7 +41,7 @@
}
async function fileSystemCreated() {
UI.viewManager.showView('sources.search');
UI.viewManager.showView('search.search');
var uiSourceCodes = fileSystemUISourceCodes();
for (var i = 0; i < uiSourceCodes.length; ++i) {
......@@ -80,7 +80,7 @@
function testSearch(next) {
var query = 'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -98,7 +98,7 @@
var query = 'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, true, false);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, false);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
}
];
......
......@@ -10,7 +10,7 @@
await TestRunner.showPanel('sources');
await TestRunner.loadHTML(`<iframe src="resources/search.html"></iframe>`);
UI.viewManager.showView('sources.search');
UI.viewManager.showView('search.search');
var scope = new Sources.SourcesSearchScope();
await Promise.all([
TestRunner.waitForUISourceCode('search.html'),
......@@ -22,7 +22,7 @@
function testIgnoreCaseAndIgnoreDynamicScript(next) {
var query = 'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -30,14 +30,14 @@
Common.settingForTest('searchInAnonymousAndContentScripts').set(true);
var query = 'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
function testCaseSensitive(next) {
var query = 'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, false /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, false /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -45,7 +45,7 @@
var query = 'searchTest' +
'UniqueString' +
' file:html';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -53,7 +53,7 @@
var query = 'file:js ' +
'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -62,7 +62,7 @@
'searchTest' +
'UniqueString' +
' file:html';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -71,7 +71,7 @@
'Unique' +
' space' +
' String';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -81,7 +81,7 @@
'Unique' +
' space' +
' String';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -92,7 +92,7 @@
' space' +
' String' +
' file:search';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -103,7 +103,7 @@
' space' +
' String' +
' file:search file:html';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -113,7 +113,7 @@
' file:html' +
' space' +
' String';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -124,7 +124,7 @@
' space' +
' String' +
' file:search';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -136,7 +136,7 @@
' space' +
' String' +
' file:search';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -146,7 +146,7 @@
' -file:css' +
' space' +
' String';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
},
......@@ -155,7 +155,7 @@
var query = 'searchTest' +
'Unique' +
' file:127.0.0.1';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, step2);
function step2() {
......@@ -163,7 +163,7 @@
query = 'searchTest' +
'Unique' +
' file:128.0.0.1';
searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
}
},
......@@ -179,7 +179,7 @@
' BAR');
var query = 'searchTest' +
'UniqueString';
var searchConfig = new Workspace.SearchConfig(query, true /* ignoreCase */, false /* isRegex */);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true /* ignoreCase */, false /* isRegex */);
SourcesTestRunner.runSearchAndDumpResults(scope, searchConfig, next);
}
}
......
......@@ -7,7 +7,7 @@
await TestRunner.showPanel('sources');
function dumpParsedSearchQuery(query, isRegex) {
var searchConfig = new Workspace.SearchConfig(query, true, isRegex);
var searchConfig = new Search.SearchConfig('sources.search-in-files', query, true, isRegex);
TestRunner.addResult('Dumping parsed search query [' + query + ']:');
TestRunner.addResult(JSON.stringify(searchConfig.queries()));
}
......
......@@ -594,6 +594,11 @@ all_devtools_files = [
"front_end/sdk/TracingModel.js",
"front_end/sdk_test_runner/module.json",
"front_end/sdk_test_runner/PageMockTestRunner.js",
"front_end/search/SearchConfig.js",
"front_end/search/searchResultsPane.css",
"front_end/search/SearchResultsPane.js",
"front_end/search/searchView.css",
"front_end/search/SearchView.js",
"front_end/security/lockIcon.css",
"front_end/security/mainView.css",
"front_end/security/module.json",
......@@ -631,7 +636,6 @@ all_devtools_files = [
"front_end/source_frame/xmlView.css",
"front_end/source_frame/XMLView.js",
"front_end/sources/AddSourceMapURLDialog.js",
"front_end/sources/AdvancedSearchView.js",
"front_end/sources/callStackSidebarPane.css",
"front_end/sources/CallStackSidebarPane.js",
"front_end/sources/CSSPlugin.js",
......@@ -639,8 +643,6 @@ all_devtools_files = [
"front_end/sources/debuggerPausedMessage.css",
"front_end/sources/DebuggerPausedMessage.js",
"front_end/sources/EditingLocationHistoryManager.js",
"front_end/sources/fileBasedSearchResultsPane.css",
"front_end/sources/FileBasedSearchResultsPane.js",
"front_end/sources/FilePathScoreFunction.js",
"front_end/sources/FilteredUISourceCodeListProvider.js",
"front_end/sources/GoToLineQuickOpen.js",
......@@ -667,7 +669,6 @@ all_devtools_files = [
"front_end/sources/SourcesNavigator.js",
"front_end/sources/sourcesPanel.css",
"front_end/sources/SourcesPanel.js",
"front_end/sources/sourcesSearch.css",
"front_end/sources/SourcesSearchScope.js",
"front_end/sources/sourcesView.css",
"front_end/sources/SourcesView.js",
......@@ -839,7 +840,6 @@ all_devtools_files = [
"front_end/worker_service/ServiceDispatcher.js",
"front_end/workspace/FileManager.js",
"front_end/workspace/module.json",
"front_end/workspace/SearchConfig.js",
"front_end/workspace/UISourceCode.js",
"front_end/workspace/Workspace.js",
"front_end/workspace_diff/WorkspaceDiff.js",
......@@ -1022,6 +1022,7 @@ generated_non_autostart_non_remote_modules = [
"$resources_out_dir/profiler/profiler_module.js",
"$resources_out_dir/quick_open/quick_open_module.js",
"$resources_out_dir/resources/resources_module.js",
"$resources_out_dir/search/search_module.js",
"$resources_out_dir/security/security_module.js",
"$resources_out_dir/settings/settings_module.js",
"$resources_out_dir/snippets/snippets_module.js",
......
......@@ -4,13 +4,15 @@
/**
* @implements {Workspace.ProjectSearchConfig}
*/
Workspace.SearchConfig = class {
Search.SearchConfig = class {
/**
* @param {?string} scopeType
* @param {string} query
* @param {boolean} ignoreCase
* @param {boolean} isRegex
*/
constructor(query, ignoreCase, isRegex) {
constructor(scopeType, query, ignoreCase, isRegex) {
this._scopeType = scopeType;
this._query = query;
this._ignoreCase = ignoreCase;
this._isRegex = isRegex;
......@@ -18,11 +20,19 @@ Workspace.SearchConfig = class {
}
/**
* @param {{query: string, ignoreCase: boolean, isRegex: boolean}} object
* @return {!Workspace.SearchConfig}
* @param {{scopeType: ?string, query: string, ignoreCase: boolean, isRegex: boolean}} object
* @return {!Search.SearchConfig}
*/
static fromPlainObject(object) {
return new Workspace.SearchConfig(object.query, object.ignoreCase, object.isRegex);
const scopeType = object.scopeType || null;
return new Search.SearchConfig(scopeType, object.query, object.ignoreCase, object.isRegex);
}
/**
* @return {?string}
*/
scopeType() {
return this._scopeType;
}
/**
......@@ -53,7 +63,7 @@ Workspace.SearchConfig = class {
* @return {{query: string, ignoreCase: boolean, isRegex: boolean}}
*/
toPlainObject() {
return {query: this.query(), ignoreCase: this.ignoreCase(), isRegex: this.isRegex()};
return {scopeType: this.scopeType(), query: this.query(), ignoreCase: this.ignoreCase(), isRegex: this.isRegex()};
}
_parse() {
......@@ -65,14 +75,14 @@ Workspace.SearchConfig = class {
const pattern = [
'(\\s*' + Workspace.SearchConfig.FilePatternRegex.source + '\\s*)',
'(\\s*' + Search.SearchConfig.FilePatternRegex.source + '\\s*)',
'(' + quotedPattern.source + ')',
'(' + unquotedPattern + ')',
].join('|');
const regexp = new RegExp(pattern, 'g');
const queryParts = this._query.match(regexp) || [];
/**
* @type {!Array.<!Workspace.SearchConfig.QueryTerm>}
* @type {!Array.<!Search.SearchConfig.QueryTerm>}
*/
this._fileQueries = [];
......@@ -88,7 +98,7 @@ Workspace.SearchConfig = class {
const fileQuery = this._parseFileQuery(queryPart);
if (fileQuery) {
this._fileQueries.push(fileQuery);
/** @type {!Array.<!Workspace.SearchConfig.RegexQuery>} */
/** @type {!Array.<!Search.SearchConfig.RegexQuery>} */
this._fileRegexQueries = this._fileRegexQueries || [];
this._fileRegexQueries.push(
{regex: new RegExp(fileQuery.text, this.ignoreCase ? 'i' : ''), isNegative: fileQuery.isNegative});
......@@ -141,10 +151,10 @@ Workspace.SearchConfig = class {
/**
* @param {string} query
* @return {?Workspace.SearchConfig.QueryTerm}
* @return {?Search.SearchConfig.QueryTerm}
*/
_parseFileQuery(query) {
const match = query.match(Workspace.SearchConfig.FilePatternRegex);
const match = query.match(Search.SearchConfig.FilePatternRegex);
if (!match)
return null;
const isNegative = !!match[1];
......@@ -165,18 +175,17 @@ Workspace.SearchConfig = class {
result += query.charAt(i);
}
}
return new Workspace.SearchConfig.QueryTerm(result, isNegative);
return new Search.SearchConfig.QueryTerm(result, isNegative);
}
};
// After file: prefix: any symbol except space and backslash or any symbol escaped with a backslash.
Workspace.SearchConfig.FilePatternRegex = /(-)?f(ile)?:((?:[^\\ ]|\\.)+)/;
Search.SearchConfig.FilePatternRegex = /(-)?f(ile)?:((?:[^\\ ]|\\.)+)/;
/** @typedef {!{regex: !RegExp, isNegative: boolean}} */
Workspace.SearchConfig.RegexQuery;
Search.SearchConfig.RegexQuery;
Workspace.SearchConfig.QueryTerm = class {
Search.SearchConfig.QueryTerm = class {
/**
* @param {string} text
* @param {boolean} isNegative
......@@ -186,3 +195,60 @@ Workspace.SearchConfig.QueryTerm = class {
this.isNegative = isNegative;
}
};
/**
* @interface
*/
Search.SearchResult = function() {};
Search.SearchResult.prototype = {
/**
* @return {string}
*/
label() {},
/**
* @return {number}
*/
matchesCount() {},
/**
* @param {number} index
* @return {number}
*/
matchLineNumber(index) {},
/**
* @param {number} index
* @return {string}
*/
matchLineContent(index) {},
/**
* @param {number} index
* @return {!Object}
*/
matchRevealable(index) {}
};
/**
* @interface
*/
Search.SearchScope = function() {};
Search.SearchScope.prototype = {
/**
* @param {!Search.SearchConfig} searchConfig
* @param {!Common.Progress} progress
* @param {function(!Search.SearchResult)} searchResultCallback
* @param {function(boolean)} searchFinishedCallback
*/
performSearch(searchConfig, progress, searchResultCallback, searchFinishedCallback) {},
/**
* @param {!Common.Progress} progress
*/
performIndexing(progress) {},
stopSearch() {}
};
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Sources.FileBasedSearchResultsPane = class extends Sources.SearchResultsPane {
Search.SearchResultsPane = class extends UI.VBox {
/**
* @param {!Workspace.SearchConfig} searchConfig
* @param {!Search.SearchConfig} searchConfig
*/
constructor(searchConfig) {
super(searchConfig);
super(true);
this._searchConfig = searchConfig;
/** @type {!Array<!Search.SearchResult>} */
this._searchResults = [];
this._treeOutline = new UI.TreeOutlineInShadow();
this._treeOutline.registerRequiredCSS('sources/fileBasedSearchResultsPane.css');
this.element.appendChild(this._treeOutline.element);
this._treeOutline.registerRequiredCSS('search/searchResultsPane.css');
this.contentElement.appendChild(this._treeOutline.element);
this._matchesExpandedCount = 0;
}
/**
* @override
* @param {!Sources.FileBasedSearchResult} searchResult
* @param {!Search.SearchResult} searchResult
*/
addSearchResult(searchResult) {
this._searchResults.push(searchResult);
const uiSourceCode = searchResult.uiSourceCode;
if (!uiSourceCode)
return;
this._addFileTreeElement(searchResult);
this._addTreeElement(searchResult);
}
/**
* @param {!Sources.FileBasedSearchResult} searchResult
* @param {!Search.SearchResult} searchResult
*/
_addFileTreeElement(searchResult) {
const fileTreeElement = new Sources.FileBasedSearchResultsPane.FileTreeElement(this.searchConfig, searchResult);
this._treeOutline.appendChild(fileTreeElement);
_addTreeElement(searchResult) {
const treeElement = new Search.SearchResultsPane.SearchResultsTreeElement(this._searchConfig, searchResult);
this._treeOutline.appendChild(treeElement);
// Expand until at least a certain number of matches is expanded.
if (this._matchesExpandedCount < Sources.FileBasedSearchResultsPane.matchesExpandedByDefaultCount)
fileTreeElement.expand();
this._matchesExpandedCount += searchResult.searchMatches.length;
if (this._matchesExpandedCount < Search.SearchResultsPane._matchesExpandedByDefault)
treeElement.expand();
this._matchesExpandedCount += searchResult.matchesCount();
}
};
Sources.FileBasedSearchResultsPane.matchesExpandedByDefaultCount = 20;
Sources.FileBasedSearchResultsPane.fileMatchesShownAtOnce = 20;
Search.SearchResultsPane._matchesExpandedByDefault = 20;
Search.SearchResultsPane._matchesShownAtOnce = 20;
Sources.FileBasedSearchResultsPane.FileTreeElement = class extends UI.TreeElement {
Search.SearchResultsPane.SearchResultsTreeElement = class extends UI.TreeElement {
/**
* @param {!Workspace.ProjectSearchConfig} searchConfig
* @param {!Sources.FileBasedSearchResult} searchResult
* @param {!Search.SearchConfig} searchConfig
* @param {!Search.SearchResult} searchResult
*/
constructor(searchConfig, searchResult) {
super('', true);
......@@ -72,9 +70,8 @@ Sources.FileBasedSearchResultsPane.FileTreeElement = class extends UI.TreeElemen
_updateMatchesUI() {
this.removeChildren();
const toIndex =
Math.min(this._searchResult.searchMatches.length, Sources.FileBasedSearchResultsPane.fileMatchesShownAtOnce);
if (toIndex < this._searchResult.searchMatches.length) {
const toIndex = Math.min(this._searchResult.matchesCount(), Search.SearchResultsPane._matchesShownAtOnce);
if (toIndex < this._searchResult.matchesCount()) {
this._appendSearchMatches(0, toIndex - 1);
this._appendShowMoreMatchesElement(toIndex - 1);
} else {
......@@ -94,13 +91,13 @@ Sources.FileBasedSearchResultsPane.FileTreeElement = class extends UI.TreeElemen
const fileNameSpan = createElement('span');
fileNameSpan.className = 'search-result-file-name';
fileNameSpan.textContent = this._searchResult.uiSourceCode.fullDisplayName();
fileNameSpan.textContent = this._searchResult.label();
this.listItemElement.appendChild(fileNameSpan);
const matchesCountSpan = createElement('span');
matchesCountSpan.className = 'search-result-matches-count';
const searchMatchesCount = this._searchResult.searchMatches.length;
const searchMatchesCount = this._searchResult.matchesCount();
if (searchMatchesCount === 1)
matchesCountSpan.textContent = Common.UIString('(%d match)', searchMatchesCount);
else
......@@ -117,8 +114,6 @@ Sources.FileBasedSearchResultsPane.FileTreeElement = class extends UI.TreeElemen
*/
_appendSearchMatches(fromIndex, toIndex) {
const searchResult = this._searchResult;
const uiSourceCode = searchResult.uiSourceCode;
const searchMatches = searchResult.searchMatches;
const queries = this._searchConfig.queries();
const regexes = [];
......@@ -126,13 +121,13 @@ Sources.FileBasedSearchResultsPane.FileTreeElement = class extends UI.TreeElemen
regexes.push(createSearchRegex(queries[i], !this._searchConfig.ignoreCase(), this._searchConfig.isRegex()));
for (let i = fromIndex; i < toIndex; ++i) {
const lineNumber = searchMatches[i].lineNumber;
const lineContent = searchMatches[i].lineContent;
const lineNumber = searchResult.matchLineNumber(i);
const lineContent = searchResult.matchLineContent(i);
let matchRanges = [];
for (let j = 0; j < regexes.length; ++j)
matchRanges = matchRanges.concat(this._regexMatchRanges(lineContent, regexes[j]));
const anchor = this._createAnchor(uiSourceCode, lineNumber, matchRanges[0].offset);
const anchor = Components.Linkifier.linkifyRevealable(searchResult.matchRevealable(i), '');
const numberString = numberToStringWithSpacesPadding(lineNumber + 1, 4);
const lineNumberSpan = createElement('span');
......@@ -155,7 +150,7 @@ Sources.FileBasedSearchResultsPane.FileTreeElement = class extends UI.TreeElemen
* @param {number} startMatchIndex
*/
_appendShowMoreMatchesElement(startMatchIndex) {
const matchesLeftCount = this._searchResult.searchMatches.length - startMatchIndex;
const matchesLeftCount = this._searchResult.matchesCount() - startMatchIndex;
const showMoreMatchesText = Common.UIString('Show all matches (%d more).', matchesLeftCount);
const showMoreMatchesTreeElement = new UI.TreeElement(showMoreMatchesText);
this.appendChild(showMoreMatchesTreeElement);
......@@ -164,16 +159,6 @@ Sources.FileBasedSearchResultsPane.FileTreeElement = class extends UI.TreeElemen
this._showMoreMatchesElementSelected.bind(this, showMoreMatchesTreeElement, startMatchIndex);
}
/**
* @param {!Workspace.UISourceCode} uiSourceCode
* @param {number} lineNumber
* @param {number} columnNumber
* @return {!Element}
*/
_createAnchor(uiSourceCode, lineNumber, columnNumber) {
return Components.Linkifier.linkifyRevealable(uiSourceCode.uiLocation(lineNumber, columnNumber), '');
}
/**
* @param {string} lineContent
* @param {!Array.<!TextUtils.SourceRange>} matchRanges
......@@ -208,7 +193,7 @@ Sources.FileBasedSearchResultsPane.FileTreeElement = class extends UI.TreeElemen
*/
_showMoreMatchesElementSelected(showMoreMatchesTreeElement, startMatchIndex) {
this.removeChild(showMoreMatchesTreeElement);
this._appendSearchMatches(startMatchIndex, this._searchResult.searchMatches.length);
this._appendSearchMatches(startMatchIndex, this._searchResult.matchesCount());
return false;
}
};
{
"extensions": [
{
"type": "view",
"location": "drawer-view",
"id": "search.search",
"title": "Search",
"persistence": "closeable",
"order": 100,
"className": "Search.SearchView"
},
{
"type": "action",
"actionId": "search.all",
"title": "Search all files",
"className": "Search.SearchView.ActionDelegate",
"category": "DevTools",
"bindings": [
{
"platform": "mac",
"shortcut": "Meta+Alt+F"
},
{
"platform": "windows,linux",
"shortcut": "Ctrl+Shift+F"
}
]
},
{
"type": "context-menu-item",
"location": "mainMenu/default",
"actionId": "search.all"
}
],
"dependencies": [
"components"
],
"scripts": [
"SearchView.js",
"SearchConfig.js",
"SearchResultsPane.js"
],
"resources": [
"searchResultsPane.css",
"searchView.css"
]
}
......@@ -35,6 +35,7 @@
{ "name": "perf_ui" },
{ "name": "profiler" },
{ "name": "quick_open" },
{ "name": "search" },
{ "name": "settings" },
{ "name": "snippets" },
{ "name": "source_frame" },
......
......@@ -131,7 +131,7 @@ Sources.NavigatorView = class extends UI.VBox {
*/
static appendSearchItem(contextMenu, path) {
function searchPath() {
Sources.AdvancedSearchView.openSearch('', path.trim());
Search.SearchView.openSearch('sources.search-in-files', `file:${path.trim()}`);
}
let searchLabel = Common.UIString('Search in folder');
......
......@@ -26,13 +26,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @implements {Sources.SearchScope}
* @unrestricted
* @implements {Search.SearchScope}
*/
Sources.SourcesSearchScope = class {
constructor() {
// FIXME: Add title once it is used by search controller.
this._searchId = 0;
/** @type {!Array<!Workspace.UISourceCode>} */
this._searchResultCandidates = [];
/** @type {?function(!Search.SearchResult)} */
this._searchResultCallback = null;
/** @type {?function(boolean)} */
this._searchFinishedCallback = null;
/** @type {?Workspace.ProjectSearchConfig} */
this._searchConfig = null;
}
/**
......@@ -91,7 +98,7 @@ Sources.SourcesSearchScope = class {
* @override
* @param {!Workspace.ProjectSearchConfig} searchConfig
* @param {!Common.Progress} progress
* @param {function(!Sources.FileBasedSearchResult)} searchResultCallback
* @param {function(!Search.SearchResult)} searchResultCallback
* @param {function(boolean)} searchFinishedCallback
*/
performSearch(searchConfig, progress, searchResultCallback, searchFinishedCallback) {
......@@ -112,7 +119,8 @@ Sources.SourcesSearchScope = class {
const promise =
project
.findFilesMatchingSearchRequest(searchConfig, filesMathingFileQuery, findMatchingFilesInProjectProgress)
.then(this._processMatchingFilesForProject.bind(this, this._searchId, project, filesMathingFileQuery));
.then(this._processMatchingFilesForProject.bind(
this, this._searchId, project, searchConfig, filesMathingFileQuery));
promises.push(promise);
}
......@@ -138,7 +146,7 @@ Sources.SourcesSearchScope = class {
continue;
if (dirtyOnly && !uiSourceCode.isDirty())
continue;
if (this._searchConfig.filePathMatchesFileQuery(uiSourceCode.fullDisplayName()))
if (searchConfig.filePathMatchesFileQuery(uiSourceCode.fullDisplayName()))
result.push(uiSourceCode.url());
}
result.sort(String.naturalOrderComparator);
......@@ -148,10 +156,11 @@ Sources.SourcesSearchScope = class {
/**
* @param {number} searchId
* @param {!Workspace.Project} project
* @param {!Workspace.ProjectSearchConfig} searchConfig
* @param {!Array<string>} filesMathingFileQuery
* @param {!Array<string>} files
*/
_processMatchingFilesForProject(searchId, project, filesMathingFileQuery, files) {
_processMatchingFilesForProject(searchId, project, searchConfig, filesMathingFileQuery, files) {
if (searchId !== this._searchId) {
this._searchFinishedCallback(false);
return;
......@@ -159,7 +168,7 @@ Sources.SourcesSearchScope = class {
files.sort(String.naturalOrderComparator);
files = files.intersectOrdered(filesMathingFileQuery, String.naturalOrderComparator);
const dirtyFiles = this._projectFilesMatchingFileQuery(project, this._searchConfig, true);
const dirtyFiles = this._projectFilesMatchingFileQuery(project, searchConfig, true);
files = files.mergeOrdered(dirtyFiles, String.naturalOrderComparator);
const uiSourceCodes = [];
......@@ -274,3 +283,62 @@ Sources.SourcesSearchScope = class {
++this._searchId;
}
};
/**
* @implements {Search.SearchResult}
*/
Sources.FileBasedSearchResult = class {
/**
* @param {!Workspace.UISourceCode} uiSourceCode
* @param {!Array.<!Common.ContentProvider.SearchMatch>} searchMatches
*/
constructor(uiSourceCode, searchMatches) {
this._uiSourceCode = uiSourceCode;
this._searchMatches = searchMatches;
}
/**
* @override
* @return {string}
*/
label() {
return this._uiSourceCode.fullDisplayName();
}
/**
* @override
* @return {number}
*/
matchesCount() {
return this._searchMatches.length;
}
/**
* @override
* @param {number} index
* @return {number}
*/
matchLineNumber(index) {
return this._searchMatches[index].lineNumber;
}
/**
* @override
* @param {number} index
* @return {string}
*/
matchLineContent(index) {
return this._searchMatches[index].lineContent;
}
/**
* @override
* @param {number} index
* @return {!Object}
*/
matchRevealable(index) {
const match = this._searchMatches[index];
return this._uiSourceCode.uiLocation(match.lineNumber, match.columnNumber);
}
};
......@@ -150,23 +150,6 @@
}
]
},
{
"type": "action",
"actionId": "sources.search.toggle",
"title": "Search all files",
"className": "Sources.AdvancedSearchView.ActionDelegate",
"category": "DevTools",
"bindings": [
{
"platform": "mac",
"shortcut": "Meta+Alt+F"
},
{
"platform": "windows,linux",
"shortcut": "Ctrl+Shift+F"
}
]
},
{
"type": "action",
"category": "Debugger",
......@@ -251,11 +234,6 @@
"prefix": "@",
"className": "Sources.OutlineQuickOpen"
},
{
"type": "context-menu-item",
"location": "mainMenu/default",
"actionId": "sources.search.toggle"
},
{
"type": "context-menu-item",
"location": "navigatorMenu/default",
......@@ -573,15 +551,6 @@
}
]
},
{
"type": "view",
"location": "drawer-view",
"id": "sources.search",
"title": "Search",
"persistence": "closeable",
"order": 100,
"className": "Sources.AdvancedSearchView"
},
{
"type": "view",
"location": "drawer-view",
......@@ -844,10 +813,17 @@
"shortcut": "Ctrl+."
}
]
},
{
"type": "@Search.SearchScope",
"id": "sources.search-in-files",
"className": "Sources.SourcesSearchScope",
"title": "Search files"
}
],
"dependencies": [
"components",
"search",
"source_frame",
"snippets",
"extensions",
......@@ -885,8 +861,6 @@
"SourceFormatter.js",
"OpenFileQuickOpen.js",
"SourcesView.js",
"AdvancedSearchView.js",
"FileBasedSearchResultsPane.js",
"SourcesSearchScope.js",
"SourcesPanel.js",
"JavaScriptCompilerPlugin.js",
......@@ -895,7 +869,6 @@
"resources": [
"callStackSidebarPane.css",
"debuggerPausedMessage.css",
"fileBasedSearchResultsPane.css",
"javaScriptBreakpointsSidebarPane.css",
"navigatorTree.css",
"navigatorView.css",
......@@ -903,7 +876,6 @@
"scopeChainSidebarPane.css",
"serviceWorkersSidebar.css",
"sourcesPanel.css",
"sourcesSearch.css",
"sourcesView.css",
"threadsSidebarPane.css",
"watchExpressionsSidebarPane.css",
......
......@@ -45,15 +45,15 @@ SourcesTestRunner.runSearchAndDumpResults = function(scope, searchConfig, callba
function searchFinishedCallback() {
function comparator(searchResultA, searchResultB) {
return searchResultA.uiSourceCode.url().compareTo(searchResultB.uiSourceCode.url());
return searchResultA._uiSourceCode.url().compareTo(searchResultB._uiSourceCode.url());
}
searchResults.sort(comparator);
for (let i = 0; i < searchResults.length; ++i) {
const searchResult = searchResults[i];
const uiSourceCode = searchResult.uiSourceCode;
const searchMatches = searchResult.searchMatches;
const uiSourceCode = searchResult._uiSourceCode;
const searchMatches = searchResult._searchMatches;
if (!searchMatches.length)
continue;
......
......@@ -6,7 +6,6 @@
],
"scripts": [
"FileManager.js",
"SearchConfig.js",
"UISourceCode.js",
"Workspace.js"
]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment