@@ -65,7 +65,9 @@ define(function (require, exports, module) {
6565 */
6666 const defaultIgnoreGlobs = [
6767 "node_modules" ,
68+ "**/node_modules" ,
6869 "bower_components" ,
70+ "**/bower_components" ,
6971 ".npm" ,
7072 ".yarn" ,
7173 "__pycache__" ,
@@ -338,6 +340,8 @@ define(function (require, exports, module) {
338340 * ProjectManager.getAllFiles().
339341 */
340342 ProjectModel . prototype . _allFilesCachePromise = null ;
343+ ProjectModel . prototype . _allFilesScopeCachePromise = null ;
344+ ProjectModel . prototype . _allFilesScope = null ;
341345
342346 /**
343347 * Sets whether the file tree is focused or not.
@@ -457,7 +461,7 @@ define(function (require, exports, module) {
457461 * starting up. The cache is cleared on every filesystem change event, and
458462 * also on project load and unload.
459463 *
460- * @param {boolean } true to sort files by their paths
464+ * @param {boolean } sort true to sort files by their paths
461465 * @return {$.Promise.<Array.<File>> }
462466 */
463467 ProjectModel . prototype . _getAllFilesCache = function _getAllFilesCache ( sort ) {
@@ -496,6 +500,49 @@ define(function (require, exports, module) {
496500 return this . _allFilesCachePromise ;
497501 } ;
498502
503+ ProjectModel . prototype . _getAllFilesInScopeCache = function ( sort , scope ) {
504+ let self = this ;
505+ if ( ! this . isWithinProject ( scope ) ) {
506+ return ( new $ . Deferred ( ) ) . reject (
507+ new Error ( `Scope ${ scope . fullPath } should be within project root ${ self . projectRoot } ` )
508+ ) . promise ( ) ;
509+ }
510+ if ( ! this . _allFilesScopeCachePromise || this . _allFilesScope !== scope ) {
511+ this . _allFilesScope = scope ;
512+ const deferred = new $ . Deferred ( ) ,
513+ allFiles = [ ] ,
514+ allFilesVisitor = function ( entry ) {
515+ if ( shouldIndex ( entry ) || entry . fullPath === scope . fullPath ) {
516+ if ( entry . isFile ) {
517+ allFiles . push ( entry ) ;
518+ }
519+ return true ;
520+ }
521+ return false ;
522+ } ;
523+
524+ this . _allFilesScopeCachePromise = deferred . promise ( ) ;
525+
526+ const scopeTimer = PerfUtils . markStart ( "Project scope files cache: " +
527+ scope . fullPath ) ,
528+ options = {
529+ sortList : sort
530+ } ;
531+
532+ scope . visit ( allFilesVisitor , options , function ( err ) {
533+ if ( err ) {
534+ PerfUtils . finalizeMeasurement ( scopeTimer ) ;
535+ deferred . reject ( err ) ;
536+ } else {
537+ PerfUtils . addMeasurement ( scopeTimer ) ;
538+ deferred . resolve ( allFiles ) ;
539+ }
540+ } . bind ( this ) ) ;
541+ }
542+
543+ return this . _allFilesScopeCachePromise ;
544+ } ;
545+
499546 /**
500547 * Returns an Array of all files for this project, optionally including
501548 * files additional files provided. Files are filtered out by shouldShow().
@@ -504,26 +551,34 @@ define(function (require, exports, module) {
504551 * the file list (does not filter directory traversal). API matches Array.filter().
505552 * @param {Array.<File>= } additionalFiles Additional files to include (for example, the WorkingSet)
506553 * Only adds files that are *not* under the project root or untitled documents.
507- * @param {boolean } true to sort files by their paths
554+ * @param {boolean } sort true to sort files by their paths
555+ * @param {Object } options optional path within project to narrow down the search
556+ * @param {File } options.scope optional path within project to narrow down the search
508557 *
509558 * @return {$.Promise } Promise that is resolved with an Array of File objects.
510559 */
511- ProjectModel . prototype . getAllFiles = function getAllFiles ( filter , additionalFiles , sort ) {
560+ ProjectModel . prototype . getAllFiles = function getAllFiles ( filter , additionalFiles , sort , options ) {
512561 // The filter and includeWorkingSet params are both optional.
513562 // Handle the case where filter is omitted but includeWorkingSet is
514563 // specified.
515- if ( additionalFiles === undefined && typeof ( filter ) !== "function" ) {
564+ if ( typeof ( filter ) !== "function" ) {
565+ options = sort ;
566+ sort = additionalFiles ;
516567 additionalFiles = filter ;
517568 filter = null ;
518569 }
570+ options = options || { } ;
519571
520572 var filteredFilesDeferred = new $ . Deferred ( ) ;
521573
522574 // First gather all files in project proper
523575 // Note that with proper promises we may be able to fix this so that we're not doing this
524576 // anti-pattern of creating a separate deferred rather than just chaining off of the promise
525577 // from _getAllFilesCache
526- this . _getAllFilesCache ( sort ) . done ( function ( result ) {
578+ const getAllFilesFn = options . scope ?
579+ this . _getAllFilesInScopeCache . bind ( this ) : this . _getAllFilesCache . bind ( this ) ;
580+ getAllFilesFn ( sort , options . scope ) . done ( function ( result ) {
581+ result = [ ...result ] ; // clone it as the above result is cached and we dont want to modify the cache
527582 // Add working set entries, if requested
528583 if ( additionalFiles ) {
529584 additionalFiles . forEach ( function ( file ) {
@@ -565,6 +620,8 @@ define(function (require, exports, module) {
565620 */
566621 ProjectModel . prototype . _resetCache = function _resetCache ( ) {
567622 this . _allFilesCachePromise = null ;
623+ this . _allFilesScopeCachePromise = null ;
624+ this . _allFilesScope = null ;
568625 } ;
569626
570627 /**
0 commit comments