Skip to content

Commit

Permalink
Update literal paths (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
snewcomer authored and dcyriller committed Jul 29, 2019
1 parent 622f1a4 commit 7e3fb9f
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 5 deletions.
6 changes: 6 additions & 0 deletions __testfixtures__/literal.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import { hasMany, belongsTo } from 'ember-data/relationships';
import JSONAPIAdapter from 'ember-data/adapters/json-api';
import { InvalidError, ServerError, TimeoutError, NotFoundError } from 'ember-data/adapter/error';
import Transform from '@ember-data/serializer/transform';
4 changes: 4 additions & 0 deletions __testfixtures__/literal.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Model, { attr, hasMany, belongsTo } from '@ember-data/model';
import JSONAPIAdapter from '@ember-data/adapter/json-api';
import { InvalidError, ServerError, TimeoutError, NotFoundError } from '@ember-data/adapter/error';
import Transform from '@ember-data/serializer/transform';
6 changes: 4 additions & 2 deletions bin/ember-data-codemod.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ function buildReport() {

// Find all of the temporary logs from the worker processes, which contain a
// serialized JSON array on each line.
glob('ember-modules-codemod.tmp.*', (err, logs) => {
glob('ember-data-codemod.tmp.*', (err, logs) => {
// If no worker found an unexpected value, nothing to report.
if (!logs) {
return;
Expand Down Expand Up @@ -143,7 +143,9 @@ function buildReport() {
);
} else {
console.log(
chalk.green('\nDone! All uses of the Ember global have been updated.')
chalk.green(
'\nDone! All uses of the Ember global and Ember Data imports have been updated.'
)
);
}
});
Expand Down
83 changes: 80 additions & 3 deletions transforms/globals-to-ember-data-imports.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function transform(file, api /*, options*/) {
// Now that we've identified all of the replacements that we need to do, we'll
// make sure to either add new `import` declarations, or update existing ones
// to add new named exports or the default export.
updateOrCreateImportDeclarations(root, modules);
updateOrCreateImportDeclarations(root, modules, mappings);

// Actually go through and replace each usage of `DS.whatever` with the
// imported binding (`whatever`).
Expand Down Expand Up @@ -157,6 +157,76 @@ function transform(file, api /*, options*/) {
return dsUsages.filter(isDSGlobal(globalDS)).paths();
}

/*
* loops through all modules and replaces literal path if necessary
* 'ember-data/model' -> '@ember-data/model'
*/
function updateExistingLiteralPaths(root, module, mappings) {
let foundMapping = mappings[module.local];

if (foundMapping) {
let newSource = foundMapping.source;
if (module.source !== newSource) {
root
.find(j.ImportDeclaration, {
source: {
type: 'Literal',
value: module.source
}
})
.find(j.Literal)
.forEach(importLiteral => {
j(importLiteral).replaceWith(j.literal(newSource));
});
}
}
}

/*
* After modifying existing sources to their new paths, we need
* to make sure we clean up duplicate imports
*/
function cleanupDuplicateLiteralPaths() {
const uniqueImports = {};

root.find(j.ImportDeclaration).forEach(nodePath => {
let node = nodePath.node;
let value = node.source && node.source.value;

if (!(value in uniqueImports)) {
// add to found uniqueImports and we wont modify
uniqueImports[value] = nodePath;
} else {
// get all specifiers and add to existing import
// then delete this nodePath
let specifiers = node.specifiers;
let existingNodePath = uniqueImports[value];

specifiers.forEach(spec => {
let local = spec.local;
let imported = spec.imported;

if (imported === 'default') {
let specifier = j.importDefaultSpecifier(j.identifier(local));
// default imports go at front
existingNodePath.get('specifiers').unshift(specifier);
} else if (imported && local) {
let specifier = j.importSpecifier(
j.identifier(imported.name),
j.identifier(local.name)
);
existingNodePath.get('specifiers').push(specifier);
} else {
let specifier = j.importSpecifier(j.identifier(local.name));
existingNodePath.get('specifiers').push(specifier);
}
});

nodePath.prune();
}
});
}

// Find destructured global aliases for fields on the DS global
function findGlobalDSAliases(root, globalDS, mappings) {
let aliases = {};
Expand Down Expand Up @@ -436,7 +506,7 @@ function transform(file, api /*, options*/) {
return parent.node.id.name === local;
}

function updateOrCreateImportDeclarations(root, registry) {
function updateOrCreateImportDeclarations(root, registry, mappings) {
let body = root.get().value.program.body;

registry.modules.forEach(mod => {
Expand All @@ -448,12 +518,12 @@ function transform(file, api /*, options*/) {
let declaration = root.find(j.ImportDeclaration, {
source: { value: mod.source }
});

if (declaration.size() > 0) {
let specifier;

if (imported === 'default') {
specifier = j.importDefaultSpecifier(j.identifier(local));
// default imports go at front
declaration.get('specifiers').unshift(specifier);
} else {
specifier = j.importSpecifier(
Expand All @@ -472,7 +542,14 @@ function transform(file, api /*, options*/) {
mod.node = importStatement;
}
}

// Update literal paths based on mappings from 'ember-data/model' to '@ember-data/model'
// by pushing into existing declaration specifiers
updateExistingLiteralPaths(root, mod, mappings);
});

// then remove old duplicate specifier if found
cleanupDuplicateLiteralPaths();
}

function findExistingModules(root) {
Expand Down

0 comments on commit 7e3fb9f

Please sign in to comment.