Skip to content

autoimport completions #1553

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

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open

autoimport completions #1553

wants to merge 14 commits into from

Conversation

iisaduan
Copy link
Member

@iisaduan iisaduan commented Aug 11, 2025

This PR implements autoimports, and allows symbols to be autoimported through completions. Also ports the basic functionalities of the changetracker (adds changes and calculates/formats the output string).

demo (note: the formatting has been fixed, see test cases)

corsa.completion.autoimports.1.mp4

Notes on implementation:

  • Caching structures (like ExportInfoMap, ImportMap, etc) have been ported for functionality, but are not saved between server requests). After the ls is more fully implemented and perf tested, we will revisit to see what caching we need to do
  • The IncludeCompletionsForModuleExports and IncludeCompletionsForImportStatements in the UserPreferences passed into any completion get/resolve request has been set to true to allow autoimports to work autoimport completions #1553 (comment)
  • changetracker formatting workarounds: autoimport completions #1553 (comment)

Related features to be implemented after this PR:

  • autoimport user settings/format settings
  • package json autoimport provider (probably mostly a rewrite)
  • organize imports
  • codefix provider (to be able to use autoimports without completions)

@alexwork1611
Copy link

I'm gonna closely follow this one...

@iisaduan
Copy link
Member Author

iisaduan commented Aug 11, 2025

bug squashing atm :). Hopefully it'll be ready soon

@iisaduan iisaduan marked this pull request as ready for review August 15, 2025 17:40
@Copilot Copilot AI review requested due to automatic review settings August 15, 2025 17:40
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements autoimports functionality, enabling automatic import suggestions through completions in the TypeScript language server. The implementation adds the ability to suggest and automatically import symbols from other modules when typing identifiers.

Key changes include:

  • Added comprehensive autoimport completion system with export info mapping and module specifier resolution
  • Implemented import statement completion support for various import syntaxes
  • Added text change tracking infrastructure for code modifications

Reviewed Changes

Copilot reviewed 51 out of 51 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
internal/ls/completions.go Main autoimport logic including export collection, module specifier resolution, and completion item generation
internal/ls/autoimportstypes.go Type definitions for import/export kinds, import fixes, and related data structures
internal/ls/changetrackerimpl.go Change tracking implementation for applying text edits and code modifications
internal/printer/changetrackerwriter.go Writer implementation for tracking position changes during code generation
internal/modulespecifiers/specifiers.go Enhanced module specifier generation with autoimport support
internal/ls/organizeimports.go Import organization utilities and comparison functions
Various utility files Helper functions, type conversions, and API enhancements to support autoimport functionality

@@ -139,7 +139,7 @@ func getActualIndentationForListItem(node *ast.Node, sourceFile *ast.SourceFile,
// VariableDeclarationList has no wrapping tokens
return -1
}
containingList := getContainingList(node, sourceFile)
containingList := GetContainingList(node, sourceFile)
Copy link
Member

Choose a reason for hiding this comment

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

I didn't know this func existed; I wonder if it's general enough to use for sig help. (No action needed, just opining)

}

func findFirstNonWhitespaceColumn(startPos int, endPos int, sourceFile *ast.SourceFile, options *FormatCodeSettings) int {
func FindFirstNonWhitespaceColumn(startPos int, endPos int, sourceFile *ast.SourceFile, options *FormatCodeSettings) int {
Copy link
Member

Choose a reason for hiding this comment

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

I am suspicious of this function, given it appears to return the column in terms of runes? I'm not sure it walks the chars correctly either, hmm...

Copy link
Member

Choose a reason for hiding this comment

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

This is what I was writing when I first went "wait, do we work in runes or in byte offsets for columns? Looks inconsistent right now". Both ways look wrong to some part of the stack around here because of that inconsistency.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I think we need everything to be UTF-8 byte offsets, until they hit the LS and get converted based on the client preferences.

The only exception might be symbol baselines (UTF-16 compat?), source maps, and maybe the API, and maybe printed diagnostics? (That's a lot of exceptions...)

Related, #1578

@jakebailey
Copy link
Member

The import in the demo is inserted in a non-pretty way; is that something being worked on?

@iisaduan
Copy link
Member Author

iisaduan commented Aug 15, 2025

The import in the demo is inserted in a non-pretty way; is that something being worked on?

Yes, this is a formatting bug/limitation. Strada formats with a sourceFileLike, and theres a lot of places in the formatter where synthesized nodes aren't handled

Edit: Fixed with help from @weswigham New statements come out pretty now (haven't updated the demo vid yet tho)

@jakebailey jakebailey requested a review from weswigham August 15, 2025 21:26
@iisaduan iisaduan changed the title [DRAFT] autoimport autoimport completions Aug 15, 2025
@@ -0,0 +1,145 @@
package fourslash_test
Copy link
Member

Choose a reason for hiding this comment

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

Technically the tests in internal/fourslash/tests/manual/ are supposed to be generated tests that had to be manually modified, and new tests go into internal/fourslash/tests/, though that doesn't have practical differences I think other than our own organization of things.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I would suggest moving this file for clarity.

}

if defaultImport != nil {
// Debug.assert(!clause.name, "Cannot add a default import to an import clause that already has one");
Copy link
Member

@gabritto gabritto Aug 15, 2025

Choose a reason for hiding this comment

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

If #1593 gets merged before this PR, this can be updated. 🙂

Copy link
Member

@gabritto gabritto left a comment

Choose a reason for hiding this comment

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

This looks good, just had a couple comments and some (many? 😅) questions

ExportKindModule ExportKind = 4
)

func (k ExportKind) String() string {
Copy link
Member

Choose a reason for hiding this comment

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

You could use stringer to generate this, if you do need the method.

@jakebailey
Copy link
Member

jakebailey commented Aug 18, 2025

Tried it out, nice:

image

But, the import did appear with the wrong indent level:

image

(I am ignoring the ordering, since that's a different problem.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants