Repository: ember-cli/ember-cli
Pull request #7239 (2017-07-19 20:37:22)

Removes private `_mergeTrees` function
`_mergeTrees` served as a proxy around `mergeTrees` module; it doesn't seem to provide a lot of value.

I had to refactor out tests a little (as some of them were spying `app._mergeTrees`) and replaced it with similar tests + a new utility.

Update:

per @rwjblue request -- it seems like addons don't rely on `app._mergeTrees`. [Search on EmberObserver](https://emberobserver.com/code-search?codeQuery=_mergeTrees) returned 3 results but after double-checking the source code, it doesn't look like any of them are still using it.


Patch:
diff --git a/blueprints/app/files/app/app.js b/blueprints/app/files/app/app.js
index b3b2bd677..c15f93593 100644
--- a/blueprints/app/files/app/app.js
+++ b/blueprints/app/files/app/app.js
@@ -1,9 +1,9 @@
-import Application from '@ember/application';
+import Ember from 'ember';
 import Resolver from './resolver';
 import loadInitializers from 'ember-load-initializers';
 import config from './config/environment';
 
-const App = Application.extend({
+const App = Ember.Application.extend({
   modulePrefix: config.modulePrefix,
   podModulePrefix: config.podModulePrefix,
   Resolver
diff --git a/blueprints/app/files/app/router.js b/blueprints/app/files/app/router.js
index d0bb00952..cdc257875 100644
--- a/blueprints/app/files/app/router.js
+++ b/blueprints/app/files/app/router.js
@@ -1,7 +1,7 @@
-import EmberRouter from '@ember/routing/router';
+import Ember from 'ember';
 import config from './config/environment';
 
-const Router = EmberRouter.extend({
+const Router = Ember.Router.extend({
   location: config.locationType,
   rootURL: config.rootURL
 });
diff --git a/blueprints/app/files/package.json b/blueprints/app/files/package.json
index a162e3606..5fed56026 100644
--- a/blueprints/app/files/package.json
+++ b/blueprints/app/files/package.json
@@ -19,7 +19,7 @@
     "ember-ajax": "^3.0.0",
     "ember-cli": "~<%= emberCLIVersion %>",
     "ember-cli-app-version": "^3.0.0",
-    "ember-cli-babel": "^6.6.0",
+    "ember-cli-babel": "^6.3.0",
     "ember-cli-dependency-checker": "^2.0.0",
     "ember-cli-eslint": "^4.0.0",
     "ember-cli-htmlbars": "^2.0.1",
diff --git a/lib/broccoli/ember-app.js b/lib/broccoli/ember-app.js
index f4621d3f3..ef3c60858 100644
--- a/lib/broccoli/ember-app.js
+++ b/lib/broccoli/ember-app.js
@@ -40,6 +40,7 @@ const Funnel = require('broccoli-funnel');
 const funnelReducer = require('broccoli-funnel-reducer');
 const logger = require('heimdalljs-logger')('ember-cli:ember-app');
 const addonProcessTree = require('../utilities/addon-process-tree');
+const lintAddonsByType = require('../utilities/lint-addons-by-type');
 const experiments = require('../experiments');
 const processModulesOnly = require('./babel-process-modules-only');
 const semver = require('semver');
@@ -654,15 +655,9 @@ class EmberApp {
     @return {Tree}        Processed tree
    */
   addonLintTree(type, tree) {
-    let output = this.project.addons.reduce((sum, addon) => {
-      if (addon.lintTree) {
-        let val = addon.lintTree(type, tree);
-        if (val) { sum.push(val); }
-      }
-      return sum;
-    }, []);
+    let output = lintAddonsByType(this.project.addons, type, tree);
 
-    return this._mergeTrees(output, {
+    return mergeTrees(output, {
       overwrite: true,
       annotation: `TreeMerger (lint ${type})`,
     });
@@ -701,7 +696,7 @@ class EmberApp {
     } else {
       let appIndex = this._rawAppIndex(htmlName, true);
       let srcIndex = this._rawSrcIndex(htmlName);
-      index = this._mergeTrees([appIndex, srcIndex], { overwrite: true });
+      index = mergeTrees([appIndex, srcIndex], { overwrite: true });
     }
 
     return new ConfigReplace(index, this._configTree(), {
@@ -785,7 +780,7 @@ class EmberApp {
         trees.push(this.podTemplates());
       }
 
-      this._cachedTemplateTree = this._mergeTrees(trees, {
+      this._cachedTemplateTree = mergeTrees(trees, {
         annotation: 'TreeMerge (templates)',
       });
     }
@@ -851,7 +846,7 @@ class EmberApp {
       trees.push(this.trees.public);
     }
 
-    return this._mergeTrees(trees, {
+    return mergeTrees(trees, {
       overwrite: true,
       annotation: 'TreeMerge (public)',
     });
@@ -869,7 +864,7 @@ class EmberApp {
       this._filterAppTree()
     ).filter(Boolean);
 
-    let mergedApp = this._mergeTrees(appTrees, {
+    let mergedApp = mergeTrees(appTrees, {
       overwrite: true,
       annotation: 'TreeMerger (app)',
     });
@@ -932,7 +927,7 @@ class EmberApp {
   */
   _processedTemplatesTree() {
     let addonTrees = this.addonTreesFor('templates');
-    let mergedTemplates = this._mergeTrees(addonTrees, {
+    let mergedTemplates = mergeTrees(addonTrees, {
       overwrite: true,
       annotation: 'TreeMerger (templates)',
     });
@@ -943,7 +938,7 @@ class EmberApp {
       annotation: 'ProcessedTemplateTree',
     });
 
-    let combinedTemplates = this._mergeTrees([
+    let combinedTemplates = mergeTrees([
       addonTemplates,
       this._templatesTree(),
     ], {
@@ -976,7 +971,7 @@ class EmberApp {
   */
   _processedTestsTree() {
     let addonTrees = this.addonTreesFor('test-support');
-    let mergedTests = this._mergeTrees(addonTrees.concat(this.trees.tests), {
+    let mergedTests = mergeTrees(addonTrees.concat(this.trees.tests), {
       overwrite: true,
       annotation: 'TreeMerger (tests)',
     });
@@ -1032,7 +1027,7 @@ class EmberApp {
     if (!this._cachedAddonTree) {
       let addonTrees = this.addonTreesFor('addon');
 
-      let combinedAddonTree = this._mergeTrees(addonTrees, {
+      let combinedAddonTree = mergeTrees(addonTrees, {
         overwrite: true,
         annotation: 'TreeMerger: `addon/` trees',
       });
@@ -1059,7 +1054,7 @@ class EmberApp {
         trees.push(this.trees.vendor);
       }
 
-      let mergedVendor = this._mergeTrees(trees, {
+      let mergedVendor = mergeTrees(trees, {
         overwrite: true,
         annotation: 'TreeMerger (vendor)',
       });
@@ -1092,7 +1087,7 @@ class EmberApp {
 
       trees = this._nodeModuleTrees().concat(trees);
 
-      let externalTree = this._mergeTrees(trees, {
+      let externalTree = mergeTrees(trees, {
         annotation: 'TreeMerger (ExternalTree)',
         overwrite: true,
       });
@@ -1102,7 +1097,7 @@ class EmberApp {
           files: Object.keys(this.amdModuleNames),
           annotation: 'Funnel (named AMD)',
         });
-        externalTree = this._mergeTrees([externalTree, shimAmd(anonymousAmd, this.amdModuleNames)], {
+        externalTree = mergeTrees([externalTree, shimAmd(anonymousAmd, this.amdModuleNames)], {
           annotation: 'TreeMerger (named AMD)',
           overwrite: true,
         });
@@ -1189,7 +1184,7 @@ class EmberApp {
     let srcTree = this._processedSrcTree();
     let trees = [this._processedAppTree(), srcTree, templates].filter(Boolean);
 
-    let app = this.addonPreprocessTree('js', this._mergeTrees(
+    let app = this.addonPreprocessTree('js', mergeTrees(
       trees,
       {
         annotation: 'TreeMerger (preprocessedApp & templates)',
@@ -1212,7 +1207,7 @@ class EmberApp {
       emberCLITree,
     ];
 
-    return this._mergeTrees(sourceTrees, {
+    return mergeTrees(sourceTrees, {
       overwrite: true,
       annotation: 'TreeMerger (appAndDependencies)',
     });
@@ -1228,7 +1223,7 @@ class EmberApp {
     let appTestTree = this.appTests(coreTestTree);
     let testFilesTree = this.testFiles(coreTestTree);
 
-    return this._mergeTrees([appTestTree, testFilesTree], {
+    return mergeTrees([appTestTree, testFilesTree], {
       annotation: 'TreeMerger (test)',
     });
   }
@@ -1244,7 +1239,7 @@ class EmberApp {
       coreTestTree
     ).filter(Boolean);
 
-    appTestTrees = this._mergeTrees(appTestTrees, {
+    appTestTrees = mergeTrees(appTestTrees, {
       overwrite: true,
       annotation: 'TreeMerger (appTestTrees)',
     });
@@ -1384,7 +1379,7 @@ class EmberApp {
       );
     }
 
-    return this._mergeTrees(vendorFiles.concat(appJs), {
+    return mergeTrees(vendorFiles.concat(appJs), {
       annotation: 'TreeMerger (vendor & appJS)',
     });
   }
@@ -1415,7 +1410,7 @@ class EmberApp {
       let options = { outputPaths: this.options.outputPaths.app.css };
       options.registry = this.registry;
 
-      let stylesAndVendor = this.addonPreprocessTree('css', this._mergeTrees(trees, {
+      let stylesAndVendor = this.addonPreprocessTree('css', mergeTrees(trees, {
         annotation: 'TreeMerger (stylesAndVendor)',
         overwrite: true,
       }));
@@ -1442,7 +1437,7 @@ class EmberApp {
         }));
       }
 
-      vendorStyles = this.addonPreprocessTree('css', this._mergeTrees(vendorStyles, {
+      vendorStyles = this.addonPreprocessTree('css', mergeTrees(vendorStyles, {
         annotation: 'TreeMerger (vendorStyles)',
         overwrite: true,
       }));
@@ -1454,7 +1449,7 @@ class EmberApp {
         vendorStyles = preprocessMinifyCss(vendorStyles, options);
       }
 
-      let mergedTrees = this._mergeTrees([
+      let mergedTrees = mergeTrees([
         preprocessedStyles,
         vendorStyles,
       ], {
@@ -1482,7 +1477,7 @@ class EmberApp {
     let external = this._processedExternalTree();
     let emberCLITree = this._processedEmberCLITree();
 
-    let addonTestSupportTree = this._mergeTrees(this.addonTreesFor('addon-test-support'), {
+    let addonTestSupportTree = mergeTrees(this.addonTreesFor('addon-test-support'), {
       overwrite: true,
       annotation: 'TreeMerger (addon-test-support)',
     });
@@ -1502,7 +1497,7 @@ class EmberApp {
 
     let footerFiles = ['vendor/ember-cli/test-support-suffix.js'];
 
-    let baseMergedTree = this._mergeTrees([emberCLITree, external, coreTestTree, finalAddonTestSupportTree]);
+    let baseMergedTree = mergeTrees([emberCLITree, external, coreTestTree, finalAddonTestSupportTree]);
     let testJs = this._concatFiles(baseMergedTree, {
       headerFiles,
       inputFiles,
@@ -1555,7 +1550,7 @@ class EmberApp {
       );
     }
 
-    return this._mergeTrees(sourceTrees, {
+    return mergeTrees(sourceTrees, {
       overwrite: true,
       annotation: 'TreeMerger (testFiles)',
     });
@@ -1581,7 +1576,7 @@ class EmberApp {
       return new Funnel(external, options);
     });
 
-    return this._mergeTrees(otherAssetTrees, {
+    return mergeTrees(otherAssetTrees, {
       annotation: 'TreeMerger (otherAssetTrees)',
     });
   }
@@ -1787,7 +1782,7 @@ class EmberApp {
     @return {Tree}                  Merged tree for this application
    */
   toTree(additionalTrees) {
-    let tree = this._mergeTrees(this.toArray().concat(additionalTrees || []), {
+    let tree = mergeTrees(this.toArray().concat(additionalTrees || []), {
       overwrite: true,
       annotation: 'TreeMerger (allTrees)',
     });
@@ -1902,16 +1897,6 @@ class EmberApp {
       content.push('}');
     }
   }
-
-  /**
-   * @private
-   * @method _mergeTrees
-   * @param {Array} trees
-   * @param {Object} options
-   */
-  _mergeTrees(trees, options) {
-    return mergeTrees(trees, options);
-  }
 }
 
 module.exports = EmberApp;
diff --git a/lib/utilities/lint-addons-by-type.js b/lib/utilities/lint-addons-by-type.js
new file mode 100644
index 000000000..c307402d3
--- /dev/null
+++ b/lib/utilities/lint-addons-by-type.js
@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = function lintAddonsByType(addons, type, tree) {
+  return addons.reduce((sum, addon) => {
+    if (addon.lintTree) {
+      let val = addon.lintTree(type, tree);
+      if (val) { sum.push(val); }
+    }
+    return sum;
+  }, []);
+};


Test patch:
diff --git a/blueprints/app/files/tests/helpers/destroy-app.js b/blueprints/app/files/tests/helpers/destroy-app.js
index e7f983bd1..c3d4d1abb 100644
--- a/blueprints/app/files/tests/helpers/destroy-app.js
+++ b/blueprints/app/files/tests/helpers/destroy-app.js
@@ -1,5 +1,5 @@
-import { run } from '@ember/runloop';
+import Ember from 'ember';
 
 export default function destroyApp(application) {
-  run(application, 'destroy');
+  Ember.run(application, 'destroy');
 }
diff --git a/blueprints/app/files/tests/helpers/module-for-acceptance.js b/blueprints/app/files/tests/helpers/module-for-acceptance.js
index 90a93bac2..5a1a583ab 100644
--- a/blueprints/app/files/tests/helpers/module-for-acceptance.js
+++ b/blueprints/app/files/tests/helpers/module-for-acceptance.js
@@ -1,8 +1,10 @@
 import { module } from 'qunit';
-import { resolve } from 'rsvp';
+import Ember from 'ember';
 import startApp from '../helpers/start-app';
 import destroyApp from '../helpers/destroy-app';
 
+const { RSVP: { resolve } } = Ember;
+
 export default function(name, options = {}) {
   module(name, {
     beforeEach() {
diff --git a/blueprints/app/files/tests/helpers/start-app.js b/blueprints/app/files/tests/helpers/start-app.js
index 681aa01a2..9a605eb8d 100644
--- a/blueprints/app/files/tests/helpers/start-app.js
+++ b/blueprints/app/files/tests/helpers/start-app.js
@@ -1,13 +1,12 @@
+import Ember from 'ember';
 import Application from '../../app';
 import config from '../../config/environment';
-import { merge } from '@ember/polyfills';
-import { run } from '@ember/runloop';
 
 export default function startApp(attrs) {
-  let attributes = merge({}, config.APP);
-  attributes = merge(attributes, attrs); // use defaults, but you can override;
+  let attributes = Ember.merge({}, config.APP);
+  attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;
 
-  return run(() => {
+  return Ember.run(() => {
     let application = Application.create(attributes);
     application.setupForTesting();
     application.injectTestHelpers();
diff --git a/tests/unit/broccoli/ember-app-test.js b/tests/unit/broccoli/ember-app-test.js
index 9ff9cddee..49a9640b1 100644
--- a/tests/unit/broccoli/ember-app-test.js
+++ b/tests/unit/broccoli/ember-app-test.js
@@ -790,26 +790,9 @@ describe('EmberApp', function() {
       });
 
       it('calls lintTree on the addon', function() {
-        app._mergeTrees = td.function();
-
-        td.when(addon.lintTree('blah', 'blam')).thenReturn('blazorz');
-
         app.addonLintTree('blah', 'blam');
 
-        td.verify(app._mergeTrees(['blazorz'], {
-          overwrite: true,
-          annotation: 'TreeMerger (lint blah)',
-        }));
-      });
-
-      it('filters out tree if lintTree returns falsey', function() {
-        app._mergeTrees = td.function();
-
-        td.when(addon.lintTree(), { ignoreExtraArgs: true }).thenReturn(false);
-
-        app.addonLintTree();
-
-        td.verify(app._mergeTrees([]), { ignoreExtraArgs: true });
+        td.verify(addon.lintTree('blah', 'blam'));
       });
     });
   });
diff --git a/tests/unit/utilities/lint-addons-by-type-test.js b/tests/unit/utilities/lint-addons-by-type-test.js
new file mode 100644
index 000000000..26ee28328
--- /dev/null
+++ b/tests/unit/utilities/lint-addons-by-type-test.js
@@ -0,0 +1,29 @@
+'use strict';
+
+const td = require('testdouble');
+const expect = require('chai').expect;
+const lintAddonsByType = require('../../../lib/utilities/lint-addons-by-type');
+
+describe('lintAddonsByType', function() {
+  let addons;
+
+  beforeEach(function() {
+    addons = [{
+      name: 'foo',
+      pkg: { name: 'foo' },
+      lintTree: td.function(),
+    }];
+  });
+
+  it('calls lintTree on the addon', function() {
+    lintAddonsByType(addons, 'app', { foo: 'bar' });
+
+    td.verify(addons[0].lintTree('app', { foo: 'bar' }));
+  });
+
+  it('filters out tree if `lintTree` returns false-y', function() {
+    td.when(addons[0].lintTree).thenReturn({});
+
+    expect(lintAddonsByType(addons, 'app')).to.deep.equal([]);
+  });
+});