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

Filter out global keywords of UMD module export declarations in completion providing auto import suggestions #42141

Merged
merged 6 commits into from
Jan 25, 2021

Conversation

aminpaks
Copy link
Contributor

@aminpaks aminpaks commented Dec 28, 2020

Please verify that:

  • There is an associated issue in the Backlog milestone (required)
  • Code is up-to-date with the master branch
  • You've successfully run gulp runtests locally
  • There are new or updated unit tests validating the change

Fixes #41761

@sandersn
Copy link
Member

From reading the issue thread, this test incorrectly passes, right? As I understood it, you wanted to create a failing test to match your observations in the editor. Is that correct?

@aminpaks
Copy link
Contributor Author

@sandersn

Yes. I don't quite understand why it works in the test but in a real env it fails (or at least in some cases fail.)

I mentioned my observation here

@andrewbranch
Copy link
Member

What Oliver said is that it fails when it’s declared as a UMD module, which this isn’t. You’d need to add export as namespace classNames too.

@andrewbranch
Copy link
Member

@aminpaks it sounds like you’re still working on this—do you want to convert the PR to a draft so it’s clear it’s not done?

@aminpaks aminpaks marked this pull request as draft January 12, 2021 19:41
@aminpaks
Copy link
Contributor Author

@andrewbranch Done. I'll look into that asap.

@aminpaks
Copy link
Contributor Author

aminpaks commented Jan 15, 2021

@andrewbranch would you tell me what is the right test case for this issue? I can't seem to reproduce it.

Update: Uh I think I understand why this test passes cos I removed the auto import suggestion from the test.

  1. Should this test only verify the auto import suggestions and not import fixes?
  2. Should it support partial word auto import suggestions or only at classNames should suggest the import?
// @filename: /SomeReactComponent.tsx
//// import * as React from 'react';
////
//// const el1 = <div className={class/*1*/}>foo</div>;

goTo.marker("1");

verify.completions({
  includes: [{
    name: "classNames",
    hasAction: true,
    source: "/node_modules/@types/classnames/index",
    sortText: completion.SortText.AutoImportSuggestions,
  }],
  preferences: {
      includeCompletionsForModuleExports: true,
  }
});

@andrewbranch
Copy link
Member

  1. My understanding from Missing auto import suggestions for UMD modules such as classnames #41761 was that the import fix works but the completions suggestion doesn’t. That’s the bug.
  2. Auto-import completions don’t need the whole identifier to be typed.

would you tell me what is the right test case for this issue

Figuring this out tends to be 90% of the work for these kinds of bugs 😄

@aminpaks
Copy link
Contributor Author

aminpaks commented Jan 16, 2021

@andrewbranch

I think I found the issue. When we add export as namespace classNames; to the module the modules carries some extra property called globalExports and then at this line it counts as a global keyword and then at this line it shadows the one that actually carries the origin with it and we lose track of the origin and that causes this line to have no action to provide the import.

I just don't have enough insights to provide a fix in the right spot that said I think we could exclude it from the global or keywords if it already has an export, what do you think?

@andrewbranch
Copy link
Member

I think for UMD exports, the global should be shadowed / filtered out if the file is already a module, unless --allowUmdGlobalAccess is set. If the file is a script or --allowUmdGlobalAccess is set, I guess there isn’t a great solution, so I would keep it as is (the global wins).

@aminpaks
Copy link
Contributor Author

aminpaks commented Jan 20, 2021

Gotcha, so would you tell me if it's okay to remove the module from global symbols if it has exports?
I found this (refer to "^^" down below) in the checker.ts that is adding the module to global symbols (apologies github doesn't allow links to that file).
Of course we must add the logic to check for allowUmdGlobalAccess compiler option also that I don't know if that's possible at this spot

            for (const file of host.getSourceFiles()) {
                if (file.redirectInfo) {
                    continue;
                }
                if (!isExternalOrCommonJsModule(file)) {
                    // It is an error for a non-external-module (i.e. script) to declare its own `globalThis`.
                    // We can't use `builtinGlobals` for this due to synthetic expando-namespace generation in JS files.
                    const fileGlobalThisSymbol = file.locals!.get("globalThis" as __String);
                    if (fileGlobalThisSymbol) {
                        for (const declaration of fileGlobalThisSymbol.declarations) {
                            diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis"));
                        }
                    }
                    mergeSymbolTable(globals, file.locals!);
                }
                if (file.jsGlobalAugmentations) {
                    mergeSymbolTable(globals, file.jsGlobalAugmentations);
                }
                if (file.patternAmbientModules && file.patternAmbientModules.length) {
                    patternAmbientModules = concatenate(patternAmbientModules, file.patternAmbientModules);
                }
                if (file.moduleAugmentations.length) {
                    (augmentations || (augmentations = [])).push(file.moduleAugmentations);
                }
                if (file.symbol && file.symbol.globalExports) {
                // ^^ this line adds the module as part of global symbols
                // adding !isExternalOrCommonJsModule(file) + the check for allowUmdGlobalAccess would fix it
                    // Merge in UMD exports with first-in-wins semantics (see #9771)
                    const source = file.symbol.globalExports;
                    source.forEach((sourceSymbol, id) => {
                        if (!globals.has(id)) {
                            globals.set(id, sourceSymbol);
                        }
                    });
                }
            }

Update: We can't add the logic there in the checker. I didn't quite get where you meant to put the logic at first but now that I think about it we should alter the shadowing logic and make it work the way you describe it

@aminpaks aminpaks force-pushed the gh-41761 branch 3 times, most recently from 674a8e1 to 6ee5516 Compare January 20, 2021 02:32
@andrewbranch
Copy link
Member

Yeah, I’m only talking about changes to completions.ts.

@aminpaks aminpaks force-pushed the gh-41761 branch 3 times, most recently from 16cd156 to 606910d Compare January 21, 2021 02:53
@aminpaks
Copy link
Contributor Author

aminpaks commented Jan 21, 2021

How do you feel about this fix @andrewbranch?

https://github.com/microsoft/TypeScript/pull/42141/files#diff-4237fd08a5f920543e184b7748bc8ae000d9b1c031810ba375b0053362ec2b6aR1530

Added two test cases, one to assert auto suggestion for module exports and the other for global keywords.

@aminpaks aminpaks changed the title Add Fourslash test for code fix import ExportEqual classnames Filter out global keywords for UMD modules if explicit exports are available Jan 21, 2021
@aminpaks aminpaks changed the title Filter out global keywords for UMD modules if explicit exports are available Filter out global keywords for UMD modules in completion providing auto import suggestions Jan 21, 2021
@aminpaks aminpaks changed the title Filter out global keywords for UMD modules in completion providing auto import suggestions Filter out global keywords of UMD module export declarations in completion providing auto import suggestions Jan 21, 2021
Copy link
Member

@andrewbranch andrewbranch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good after these small nits

src/services/completions.ts Outdated Show resolved Hide resolved
src/services/completions.ts Outdated Show resolved Hide resolved
@aminpaks aminpaks marked this pull request as ready for review January 22, 2021 23:15
Copy link
Member

@andrewbranch andrewbranch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @aminpaks!

@andrewbranch andrewbranch merged commit 290af69 into microsoft:master Jan 25, 2021
@aminpaks
Copy link
Contributor Author

My pleasure @andrewbranch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Backlog Bug PRs that fix a backlog bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Missing auto import suggestions for UMD modules such as classnames
4 participants