Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find All Reference from requiring file to module file works only if not default CommonJS exports #22222

Open
mjbvz opened this issue Feb 28, 2018 · 7 comments
Labels
Bug A bug in TypeScript VS Code Tracked There is a VS Code equivalent to this issue
Milestone

Comments

@mjbvz
Copy link
Contributor

mjbvz commented Feb 28, 2018

From @Hoishin on February 28, 2018 4:58

By "default CommonJS exports" I mean module.exports = something, rather than module.exports.foo = something or module.exports = {foo: something}

Might belong to microsoft/vscode#21507, but I thought it is a bit different.

  • VSCode Version: 1.20.1
  • OS Version: macOS High Sierra Version 10.13.3

Steps to Reproduce:

  1. module.exports something
const f = 1234;
module.exports = f;
  1. require it
const f = require('./above-file');
console.log(f);
  1. The f in console.log doesn't show references across files in Find All References. You can find references across files if you Find All References from the module file.

However,

  1. module.exports.foo something
const f = 1234;
module.exports.foo = f;
  1. require it
const {foo} = require('./above-file');
console.log(foo);
  1. The foo in console.log DOES show reference across files in Find All References. You can find references across files if you Find All References from the module file.

Does this issue occur when all extensions are disabled?: Yes

Copied from original issue: microsoft/vscode#44700

@mjbvz mjbvz self-assigned this Feb 28, 2018
@mjbvz mjbvz removed their assignment Feb 28, 2018
@mjbvz mjbvz added VS Code Tracked There is a VS Code equivalent to this issue and removed javascript labels Feb 28, 2018
@mhegazy mhegazy added the Bug A bug in TypeScript label Mar 9, 2018
@mhegazy
Copy link
Contributor

mhegazy commented Mar 9, 2018

The f in console.log doesn't show references across files in Find All References. You can find references across files if you Find All References from the module file.

The bug here is that find all references shows the f in ./above-file. the f there is a different name, and should not be in the reference set.

The foo in console.log DOES show reference across files in Find All References. You can find references across files if you Find All References from the module file.

this makes sense, since you are referencing a property on the module.

@mhegazy mhegazy assigned ghost Mar 9, 2018
@mhegazy mhegazy added this to the TypeScript 2.9 milestone Mar 9, 2018
@ghost
Copy link

ghost commented Apr 20, 2018

In importTracker I added this to isNodeImport:

case SyntaxKind.VariableDeclaration:
    return { isNamedImport: false };

But then it fails at checker.getImmediateAliasedSymbol(symbol); in getImport.
The problem is that const x = require("./x") doesn't give us an alias to the export. It just gives us a variable with the same type as the export from x.
Going forward from the export to the import works because detecting an import is based on the file being imported. But going backwards doesn't work unless we have a way of getting the original symbol.
@rbuckton @sandersn Is there a reason we don't create alias symbols at const x = require("./x") but do at import x = require("./x")?

I tested with:

/// <reference path='fourslash.ts'/>

// @allowJs: true

// @Filename: /a.ts
////function [|{| "isWriteAccess": true, "isDefinition": true |}x|]() {};
////export = [|x|];

// @Filename: /b.js
////const [|{| "isWriteAccess": true, "isDefinition": true |}x|] = require("./a");
////[|x|];

const [r0, r1, r2, r3] = test.ranges();
verify.referenceGroups(r2, [/*todo*/]);

@ghost
Copy link

ghost commented Apr 20, 2018

The following test cases crashes currently (with no modifications) because of the failure to find a symbol:

/// <reference path='fourslash.ts'/>

// @allowJs: true

// @Filename: /a.js
////function [|{| "isWriteAccess": true, "isDefinition": true |}x|]() {};
////module.exports = [|x|];

// @Filename: /b.ts
////import [|{| "isWriteAccess": true, "isDefinition": true |}x|] = require("./a");
////[|x|];

const [r0, r1, r2, r3] = test.ranges();
verify.referenceGroups(r2, [/*todo*/]);

@sandersn
Copy link
Member

Does #23570 fix this? It makes module.exports= an alias, just like export= is.

@ghost
Copy link

ghost commented Apr 20, 2018

@sandersn That fixes the second example, but it looks like const x = require("./a"); is still not an alias. So it will still crash in the first example (given the modification to isNodeImport).

@ghost
Copy link

ghost commented Jul 9, 2018

I think fixing #25533 would fix this.

@ghost ghost modified the milestones: TypeScript 3.0.1, TypeScript 3.1 Jul 10, 2018
@ghost ghost modified the milestones: TypeScript 3.1, TypeScript 3.2 Sep 17, 2018
@ghost ghost assigned sandersn and unassigned ghost Nov 16, 2018
@sandersn sandersn removed this from the TypeScript 3.3 milestone Jan 16, 2019
@sandersn sandersn added this to the TypeScript 3.4.0 milestone Jan 16, 2019
@sandersn
Copy link
Member

Typescript behaviour on this front is so broken that it needs to be fixed before fixing Javascript:

// @Filename: welove.ts
const g = 4567;
export = g;
// @Filename: app.tsx
import good = require('./welove')
console.log(good/*1*/)

Find-all-refs at /*1*/ finds all four references, which is arguable, since g and good have different names. Rename at /*1*/ renames all four references, which seems bad since g and good are not the same name, and welove.ts is likely a d.ts where renaming is going to cause a break.

// @Filename: welove.ts
const g = 4567;
export const good = g;
// @Filename: app.tsx
import { good } from './welove'
console.log(good/*1*/)

Here, find-all-refs at (1) finds the last 3 lines, which seems fine. But it does even with the import is import { good as go }, which seems wrong in the same way as the export= example. Rename is just broken. Renaming at (1) renames the last line, renames the import to import { good as go } and then incorrectly renames export const go = g.

This may be fixed in some version of VS but it's broken in VS Code and emacs. I'll see if there's an existing bug.

@sandersn sandersn modified the milestones: TypeScript 3.5.0, Backlog May 20, 2019
@sandersn sandersn removed their assignment Jan 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript VS Code Tracked There is a VS Code equivalent to this issue
Projects
None yet
Development

No branches or pull requests

4 participants