Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 5, 2025

  • Understand the issue: tsp format should clean up unused imports
  • Explore the codebase structure (compiler, formatter, name-resolver)
  • Understand how using unused detection works (via name-resolver)
  • Create a new linter rule unused-import similar to unused-using
  • Implement getUnusedImports() in the name resolver to track unused file imports
  • Add code fix support for removing unused imports (reuses existing removeUnusedCodeCodeFix)
  • Add tests for the new functionality
  • Run formatting and linting
  • Add changelog entry
  • Address code review feedback
  • Add comprehensive tests for edge cases reported in review
  • Fix: do not mark import as unused when using statement references its namespace

Summary

This PR adds a new linter rule @typespec/compiler/unused-import that detects and reports unused import statements in TypeSpec files. When enabled, it will:

  1. Show a warning (or hint by default in IDE) for imports that are not used
  2. Provide a code fix to remove the unused import
  3. Track which source files' symbols are actually referenced
  4. Correctly handle imports that provide namespaces used by using statements

The implementation follows the same pattern as the existing unused-using rule and integrates with the language server for IDE support.

Testing

Added comprehensive tests covering:

  • Multiple imports with only some unused
  • Unused import before/after used imports
  • Enums used as generic type parameters
  • Enum member access via qualified names
  • Namespace member access via qualified names
  • Import with using statement referencing its namespace
  • Import with using statement even without direct symbol usage
Original prompt

This section details on the original issue you should resolve

<issue_title>tsp format should clean up unused imports</issue_title>
<issue_description>### Clear and concise description of the problem

If I have the following two typspec files

main.tsp

import "./models.tsp";

model Foo {
  bar: String
}

models.tsp

model Bun {
  prop: String
}

I'd expect the tsp format command to clean up the unused import in the main file. Currently it does not.

Checklist

  • Follow our Code of Conduct
  • Read the docs.
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.</issue_description>

<agent_instructions>Before committing, make sure you run the formatting and linting commands.
After all the changes are done, run npx @chronus/chronus add to add a new feature changelog entry.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits December 5, 2025 17:54
- Add getUnusedImports() method to NameResolver interface
- Implement tracking of which source files' symbols are used
- Create unused-import linter rule similar to unused-using
- Add tests for unused import detection

Co-authored-by: baywet <[email protected]>
- Use getDirectoryPath, normalizePath, resolvePath from path-utils.ts
- Remove redundant transitive check logic
- Add changelog entry for unused import feature

Co-authored-by: baywet <[email protected]>
Copilot AI changed the title [WIP] Fix tsp format to clean up unused imports Add linter rule to detect unused imports Dec 5, 2025
Copilot AI requested a review from baywet December 5, 2025 18:17
@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 5, 2025

Open in StackBlitz

npm i https://pkg.pr.new/microsoft/typespec/@typespec/compiler@9149

commit: b309d52

@baywet baywet marked this pull request as ready for review December 5, 2025 18:23
@baywet baywet enabled auto-merge December 5, 2025 18:23
@baywet baywet disabled auto-merge December 5, 2025 18:43
@baywet baywet marked this pull request as draft December 5, 2025 18:43
@baywet
Copy link
Member

baywet commented Dec 5, 2025

@copilot this version has two bugs:

  • If an import is unused, all the import above will be marked as unused even though they are.
  • If an import target contains an enum definition, and the enum is used as a generic type parameter value, it'll be considered as unused even though it's used.

Start by defining unit tests for those two cases, can then implement the fixes.

- Test multiple imports with only one unused
- Test unused import before used import
- Test unused import in the middle of used imports
- Test enum used as generic type parameter
- Test enum member access via qualified name
- Test namespace member access via qualified name

Co-authored-by: baywet <[email protected]>
Copy link
Contributor Author

Copilot AI commented Dec 5, 2025

@copilot this version has two bugs:

  • If an import is unused, all the import above will be marked as unused even though they are.
  • If an import target contains an enum definition, and the enum is u...

I've added comprehensive test cases for both scenarios in commit 69d63fa. All tests pass, which suggests the current implementation handles these cases correctly:

  1. Multiple imports with one unused: Tests confirm only the unused import is flagged, not imports above/below it
  2. Enum as generic type parameter: Tests confirm Container<MyEnum> correctly marks the enum's import as used

If you're still seeing these issues, could you share a minimal reproduction case? The specific code structure may reveal an edge case I haven't covered in the tests.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • telemetry.astro.build
    • Triggering command: /usr/local/bin/node node /home/REDACTED/work/typespec/typespec/website/node_modules/.bin/../astro/astro.js build pec/node_modules/.pnpm/@esbuild&#43;. k/ty�� ebsite/src/content/docs/docs/emitters/openapi3/reference node .0_tmp_3368/node_modules/pnpm/dist/node-gyp-bin/sh -p . .0/bin/sh node /hom�� lmstxt --output-dir ../../website/src/content/docs/docs/libraries/http/reference node tools/pnpm/10.23.0_tmp_3368/node_modules/pnpm/dist/node-gyp-bin/node --no-emit sed _modules/pnpm/ditsx ./.scripts/regen-compiler-docs.ts sh (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from baywet December 5, 2025 19:17
@baywet
Copy link
Member

baywet commented Dec 5, 2025

@copilot the latest tests you've added do not cover the issues I ran into when testing the changes in a local project.

Let's start by addressing the issue of unused imports making other imports appearing as unused even though they are used. The description I provided was incomplete.

When "using TypeSpec.OpenAPI;" is present, "import @typespec/openapi;" should not be marked as unused. This is a special case for this package.
When "using TypeSpec.Http;" is present, "import @typespec/http" should not be marked as unused. This is a special case for this package.
There are probably additional special cases to add based on packages provided by this repository. Like the Streaming and SSE packages. Try to discover which namespaces they export, and then add them to the list of exceptions.

Start by updating the unit tests definitions.

… namespace

When a file has a using statement like "using MyLib;", the corresponding
import that provides the MyLib namespace should not be marked as unused.
This fixes the issue where imports for @typespec/http, @typespec/openapi,
and other packages were incorrectly flagged as unused when only their
namespaces were used via using statements.

Added tests for:
- Import with using statement referencing its namespace
- Import with using statement even without symbol usage from that namespace

Co-authored-by: baywet <[email protected]>
Copy link
Contributor Author

Copilot AI commented Dec 5, 2025

@copilot the latest tests you've added do not cover the issues I ran into when testing the changes in a local project.

Let's start by addressing the issue of unused imports making other imports app...

Fixed in commit b309d52. The getUnusedImports function now checks if any using statement references a namespace from the import. When using TypeSpec.Http; is present, the @typespec/http import will no longer be marked as unused, even if no symbols from it are directly referenced in the code.

Added tests for:

  • Import with using statement referencing its namespace
  • Import with using statement even without direct symbol usage from that namespace

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • telemetry.astro.build
    • Triggering command: /usr/local/bin/node node /home/REDACTED/work/typespec/typespec/website/node_modules/.bin/../astro/astro.js build node k/ty�� ebsite/src/content/docs/docs/emitters/openapi3/reference . cal/share/pnpm/.tools/pnpm/10.23../../website/src/content/docs/docs/emitters/protobuf/reference --import @typespec/librar-c --no-emit node k/ty�� lmstxt --output-dir ../../website/src/content/docs/docs/libraries/http/reference node _modules/pnpm/dist/node-gyp-bin/sh -p . &amp;&amp; pnpm lish node _modules/pnpm/ditsx ./.scripts/regen-compiler-docs.ts sed (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copy link
Member

Choose a reason for hiding this comment

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

just leaving comment here if this get resumed but I think the test for this are not at the correct layer, it shouldn't really need to invlove the language server

@baywet
Copy link
Member

baywet commented Dec 10, 2025

abandonning this (see reasoning in linked issue)

@baywet baywet closed this Dec 10, 2025
@baywet baywet deleted the copilot/fix-unused-imports-in-tsp-format branch December 10, 2025 15:53
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.

tsp format should clean up unused imports

3 participants