ts-morph
ts-morph copied to clipboard
fixMissingImports breaks when adding to empty named imports
I'm not sure exactly what happened here, but I had:
import { } from "../jsx";
And that caused this:
Error: Cannot get the next when at the end of the iterator.
-- Details --
Path: V:/ts-morph/src/structures/utils/forEachStructureChild.ts
Text: "...dDeclarationStructure, ParameteredNodeStructure, TypeElementMemberedNodeStructure } from \"../base\";\r\nimport { JsxElementStructure, JsxSelfClosingElementStructure, JsxAttributedNodeStructure }{ } from \"../jsx\";\r\nimport { VariableStatementStructure } from \"../statement\";\r\n\r\n// todo: Code generate this...\r\n\r\nexp..."
Stack: Error: Cannot get the next when at the end of the iterator.
at AdvancedIterator.next (V:\ts-morph\node_modules\ts-morph\dist\utils\AdvancedIterator.js:33:19)
at RangeHandler.handleNode (V:\ts-morph\node_modules\ts-morph\dist\manipulation\nodeHandlers\RangeHandler.js:38:78)
at NodeHandlerHelper.handleForValues (V:\ts-morph\node_modules\ts-morph\dist\manipulation\nodeHandlers\NodeHandlerHelper.js:12:21)
at RangeHandler.rangeHandlerReplace (V:\ts-morph\node_modules\ts-morph\dist\manipulation\nodeHandlers\RangeHandler.js:48:21)
at RangeHandler.handleNode (V:\ts-morph\node_modules\ts-morph\dist\manipulation\nodeHandlers\RangeHandler.js:31:18)
at NodeHandlerHelper.handleForValues (V:\ts-morph\node_modules\ts-morph\dist\manipulation\nodeHandlers\NodeHandlerHelper.js:12:21)
at RangeHandler.rangeHandlerReplace (V:\ts-morph\node_modules\ts-morph\dist\manipulation\nodeHandlers\RangeHandler.js:48:21)
at RangeHandler.handleNode (V:\ts-morph\node_modules\ts-morph\dist\manipulation\nodeHandlers\RangeHandler.js:31:18)
at Object.doManipulation (V:\ts-morph\node_modules\ts-morph\dist\manipulation\manipulations\doManipulation.js:9:21)
at Object.insertIntoTextRange (V:\ts-morph\node_modules\ts-morph\dist\manipulation\manipulations\insertion.js:34:22)
at Object.doManipulation (V:\ts-morph\node_modules\ts-morph\dist\manipulation\manipulations\doManipulation.js:12:15)
at Object.insertIntoTextRange (V:\ts-morph\node_modules\ts-morph\dist\manipulation\manipulations\insertion.js:34:22)
at applyTextChanges (V:\ts-morph\node_modules\ts-morph\dist\compiler\ast\module\SourceFile.js:656:32)
at SourceFile.fixMissingImports (V:\ts-morph\node_modules\ts-morph\dist\compiler\ast\module\SourceFile.js:636:13)
at Object.createForEachStructureChild (V:\ts-morph\scripts\generation\createForEachStructureChild.ts:29:31)
at Object.<anonymous> (V:\ts-morph\scripts\generation\main.ts:46:9)
at Generator.next (<anonymous>)
at V:\ts-morph\scripts\generation\main.ts:7:71
at new Promise (<anonymous>)
at __awaiter (V:\ts-morph\scripts\generation\main.ts:3:12)
Kind of looks like that might be a bug in the compiler though.
In my case I had a file no imports at all: fixMissingImports failed with:
ERROR ts-morph failed ManipulationError: Manipulation error: Error replacing tree: The children of the old and new trees were expected to have the same count (2:4).
As a workaround I:
- add a dummy import: e.g.
{ SourceFile } from 'ts-morph'; - call
fixMissingImport()which works now, that we have at least one import - call
organizeImports()which will remove the dummy import
@tmtron would you be able to add reproduction steps? That would be good for me to look into.
@dsherret I tried to reproduce it in a simple project, but the issue does not show up there. I guess it might be realted to our custom path-mappings (ref #805). Since we have the workaround, it's okay for now - when we hit the issue again or when we can reproduce it in a simple project, we'll create a new issue.
I get the same error when adding JSDoc to an interface declaration and then call fixMissingImports() on source file. Without JSDoc everything is working fine.
ManipulationError: Manipulation error: Error replacing tree: The children of the old and new trees were expected to have the same count (1:92).
Any idea?
Having the same error while adding a property to an interface
@ftomassetti does it occur after calling fixMissingImports()? If not please open up a new issue or if so, could you provide reproduction steps here? Thanks!
@dsherret @tmtron - I can confirm this occurs with my project well, and is indeed somehow solved when you have a 'dummy' import in the files you want to fix imports for. The funny thing is, I can't reproduce it in a simple usage either! I tried a simple node script, and a simple CodeSandbox in React, both worked... I'm hoping I'll find it in the next few days, I really don't like putting a random dummy import in my files.
ts-morph 11.0.0 nodejs 14.16.1
I got an error similar to what @LarsBauer had seen, and in my case I had code that looked somewhat like:
/**
* Copied from https://some.url.somewhere.on.the.web
*/
import { a, b } from 'nodeModulesPackageA'
import { c } from 'nodeModulesPackageB'
import { d } from '@pathAlias/codebaseCode'
I then removed the import { d } from '@pathAlias/codebaseCode' bit with importDeclaration.remove() and made the fixMissingImports() call.
At the end, the rewritten file would have looked something like:
/**
* Copied from https://some.url.somewhere.on.the.web
*/
import d from '@pathAlias/codebaseCode'
import { a, b } from 'nodeModulesPackageA'
import { c } from 'nodeModulesPackageB'
Once I got rid of the comment block, the file was processed correctly with fixMissingImports()
@jdfm - ahhh, so it was just the leading comment in the file? I didn't think of that, my example as well has a comment line at the top of the file! But then @dsherret - is this a bug in the implementation? I think it's acceptable that comments should not be the very first lines of a file (after calling fixMissingImports()) but I would at least not expect an error, instead that those comments would be pushed down below the imports, i.e. the imports to be inserted at the start of the file.
@jdfm - ahhh, so it was just the leading comment in the file?
That seems to have been the case for me at least. It would be interesting to hear from others if this fixes their issues as well.
I think it's acceptable that comments should not be the very first lines of a file (after calling
fixMissingImports()) [...] instead that those comments would be pushed down below the imports, i.e. the imports to be inserted at the start of the file.
So, in this case we're using the comment at the top of the file as a way of noting that we're basing our implementation on someone else's. Maybe you'd like to give extra context about a module via a code comment. There could be other use cases where a comment at the top of the file is desirable, like, maybe for licensing purposes, or for linter disabling at the file level, which is usually done with an enriched comment. The fact is, I don't know if it's fair to assume that the user wouldn't want to keep that comment at the top of the file.
[...] but I would at least not expect an error, [...]
Agreed.
@jdfm - that's true; I didn't think about things like linters or licenses.
Another repro:
import { Project } from 'ts-morph';
const project = new Project({ useInMemoryFileSystem: true });
const sourceFile = project.createSourceFile(
'test.ts',
'import foo from "./bar"; console.log(qux);'
);
project.createSourceFile('baz.ts', 'export const qux = 1;');
sourceFile.getImportDeclarations().forEach((importDeclaration) => {
importDeclaration.replaceWithText('');
});
// sourceFile.getText() is now "console.log(qux);"
sourceFile.fixMissingImports();
// Throws: Manipulation error: Error replacing tree: The children of the old and new trees were expected to have the same count (1:2).
I'm on [email protected], in case that's helpful.