Skip to content

[lints] Prevent non src/ imports from src/ #60615

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

Closed
dcharkes opened this issue Apr 24, 2025 · 5 comments
Closed

[lints] Prevent non src/ imports from src/ #60615

dcharkes opened this issue Apr 24, 2025 · 5 comments
Labels
area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages. devexp-linter Issues with the analyzer's support for the linter package P3 A lower priority bug or feature request type-enhancement A request for a change that isn't a bug

Comments

@dcharkes
Copy link
Contributor

Often lib/my_package.dart exports a bunch of lib/src/xxx.dart. When working on lib/src/abc.dart, I want to only import other src/xxx.dart files, I don't want the blanket import of the whole package that imports all public classes.

I've created a custom lint for this for the packages I work on, but maybe it would be worth it to have this lint available more generally.

import 'package:analyzer/error/listener.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';

class DontImportOutsideSrcRule extends DartLintRule {
  DontImportOutsideSrcRule() : super(code: _code);

  static const _code = LintCode(
    name: 'avoid_import_outside_src',
    problemMessage:
        "Avoid importing files outside 'lib/src/' from files within 'lib/src/'.",
    correctionMessage:
        "Files outside 'lib/src/' likely only export definitions from inside 'lib/src/'. "
        'Import the file with the definition directly.',
  );

  @override
  void run(
    CustomLintResolver resolver,
    ErrorReporter reporter,
    CustomLintContext context,
  ) {
    context.registry.addImportDirective((node) {
      final importedUri = node.uri.stringValue;
      if (importedUri == null) {
        return;
      }
      final importingFile = resolver.source.uri;

      if (importedUri.startsWith('package:')) {
        // Package imports are of no interest. Use prefer_relative_imports to
        // prevent package imports of the same package.
        return;
      }
      if (importedUri.startsWith('dart:')) {
        return;
      }
      final importedUriAbsolute = importingFile.resolve(importedUri);
      if (_isInSrcDirectory(importingFile)) {
        if (!_isInSrcDirectory(importedUriAbsolute)) {
          reporter.atNode(node, code);
        }
      }
    });
  }

  bool _isInSrcDirectory(Uri uri) {
    if (uri.toFilePath(windows: false).contains('lib/src/')) {
      return true;
    }
    if (uri.toFilePath(windows: false).contains('lib/')) {
      return false;
    }
    return false;
  }
}
@devoncarew
Copy link
Member

This issue should likely be filed against the sdk repo; that tracks creating new lints.

This package (package:lints) is about promoting current lints to our recommended sets for the community.

fwiw, the lint above sounds like it depends on some coding conventions that aren't universal; probably a good use case for the upcoming analyzer plugins work?

@devoncarew devoncarew transferred this issue from dart-lang/core Apr 24, 2025
@devoncarew devoncarew added the area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages. label Apr 24, 2025
@FMorschel
Copy link
Contributor

For visibility @srawlins.

@srawlins
Copy link
Member

I love it. Might be a good candidate for an analyzer plugin lint, when those become ready.

@srawlins srawlins added P3 A lower priority bug or feature request devexp-linter Issues with the analyzer's support for the linter package type-enhancement A request for a change that isn't a bug labels Apr 28, 2025
@lrhn
Copy link
Member

lrhn commented Apr 30, 2025

Definitely a lint that's based on some choice of modularization and file structuring.
Not something I'd want to recommend to everybody, because it may not make sense.

Also, the way many packages are written, the top-level libraries are just thin export 'src/packagename.dart'; files that exports a file in src/. Sometimes its a barrel file that exports more than one file, sometimes the barrel file itself is in src/.

This lint wouldn't do any good in the latter case, since you can just import src/mypackage.dart instead of mypackage.dart, and get all the same names imported.

And other package declare their important types and APIs in the top-level library, and only use src/ for utility functions, and those may have to import the top-level libraries.

Those are all valid approaches, not something we'd want to mandate in any direction.

@dcharkes
Copy link
Contributor Author

I'm happy if I can have custom lints.

@srawlins let's connect offline to see if we can migrate what I wrote can be rewritten in what you're working on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages. devexp-linter Issues with the analyzer's support for the linter package P3 A lower priority bug or feature request type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

5 participants