jscodeshift icon indicating copy to clipboard operation
jscodeshift copied to clipboard

statement(s) templates yields some weird stuff

Open zpdDG4gta8XKpMCd opened this issue 5 years ago • 5 comments

consider the following snippet

const statement = template.statements`const ${name} = require('${name}');
`;

the output is as follows:

const range_1 = require('$jscodeshift1441$');
const minimal_connectivity_leg_1 = require('$jscodeshift1443$');
const connectivity_path_1 = require('$jscodeshift1445$');
const connectivity_ref_1 = require('$jscodeshift1447$');
const new_connectivity_path_1 = require('$jscodeshift1449$');
const core_1 = require('$jscodeshift1451$');
const menu_1 = require('$jscodeshift1453$');
const versioned_1 = require('$jscodeshift1455$');

note, that the first use of name is correct, whereas the second one takes some of jscodeshift internals

zpdDG4gta8XKpMCd avatar Mar 10 '19 01:03 zpdDG4gta8XKpMCd

problem 1:

jscodeshift/index.js is referring to src rather than dist:

/*
 *  Copyright (c) 2015-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

module.exports = require('./src/core'); // <-- WHY SRC?

zpdDG4gta8XKpMCd avatar Mar 10 '19 03:03 zpdDG4gta8XKpMCd

problem 2:

module.exports = function withParser(parser) {
  function statements(template/*, ...nodes*/) {
    template = Array.from(template);
    const nodes = Array.from(arguments).slice(1);
    const varNames = nodes.map(() => getUniqueVarName()); // <-- SOME NEW NAMES INSTEAD OF NODES?
    const src = template.reduce( // <-- I WISH I COULD SEE MY NODES SOMEWHERE IN HERE
      (result, elem, i) => result + varNames[i - 1] + elem
    );

    return replaceNodes(
      src,
      varNames,
      nodes,
      parser
    ).program.body;
  }

zpdDG4gta8XKpMCd avatar Mar 10 '19 03:03 zpdDG4gta8XKpMCd

I ran into similar issues with quoting strings for template interpolation. I worked around it by quoting the string beforehand.

const quoted = `'${name}'`
const statement = template.statements`const ${name} = require(${quoted});
`;

neilpa avatar Oct 11 '19 23:10 neilpa

I have the same problem.

Here is a simple code to reproduce it:

module.exports = (fileInfo, api) => {
  const j = api.jscodeshift;
  
  const x = 'flo'

  return j(fileInfo.source)
    .find(j.ClassDeclaration)
    .replaceWith(path => j.template.statement`${x}('${x}',{ns: ${x}},'${x}')`
    )
    .toSource();
}

The output is like this:

flo('$jscodeshift156$', {ns: flo}, '$jscodeshift158$')

I checked the test for template and I see there is no single test for this use case. I also deduced from the tests that this is an easy way to interpolate nodes to build other nodes easier, but it doesn't have full support for 'parsing' the template. If, instead of trying to build a template with a string, you provide a string literal it works j.literal(x)

So on previous example:

j.template.statement`${x}(${j.literal(x)},{ns: ${x}},${j.literal(x)})`

yields the expected output

flo("flo", {ns: flo}, "flo")

This feature is so undocumented that is a consuming trial and error task

danielo515 avatar Nov 30 '21 11:11 danielo515

what's happening I believe is that when you break up a piece of code (identifier often, maybe any node) is that jscodeshift doesn't know how to interpolate, and this should first be turned into a single node.

In my case I had to change from:

j.template.statement`
function connect${connectorName}(renderFn) {
 const ${connectorName} = (props) => {
   const data = use${connectorName}(props);

   return renderFn({ ...props, ...data });
 };

 return ${connectorName};
}
`

to

j.template.statement`
function ${`connect${connectorName}`}(renderFn) {
  const ${connectorName} = (props) => {
    const data = ${`use${connectorName}`}(props);

    return renderFn({ ...props, ...data });
  };

  return ${connectorName};
}
`

Haroenv avatar Jul 24 '23 13:07 Haroenv