Skip to content
This repository has been archived by the owner on Aug 18, 2020. It is now read-only.

Adds no-ancestor-directory-import rule #149

Merged
merged 1 commit into from
Oct 27, 2018

Conversation

cartogram
Copy link
Contributor

@cartogram cartogram commented Aug 28, 2018

Closes #138

In addition to the code, feedback on the description and name of this rule would be really great. I found it to be a hard one to describe in words.

@cartogram cartogram force-pushed the prefer-explicit-relative-imports branch from 85bd95c to 1a6c03e Compare August 28, 2018 17:18

## Rule Details

This rule aims to...
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this sentence incomplete?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kaelig updated

@cartogram cartogram force-pushed the prefer-explicit-relative-imports branch from 1a6c03e to 008aefc Compare August 29, 2018 03:53
@cartogram cartogram force-pushed the prefer-explicit-relative-imports branch 3 times, most recently from 278b76f to e6d1fa9 Compare August 29, 2018 05:04
@cartogram cartogram requested review from ismail-syed and lemonmade and removed request for GoodForOneFare August 29, 2018 18:28
@@ -0,0 +1,27 @@
# Prefer relative local imports extend to the file from where they are importing without relying on an index file. (prefer-explicit-local-imports)
Copy link
Member

Choose a reason for hiding this comment

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

I think I might describe this more as "no ancestor directory import".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, all makes sense. I like that name.

},
};

function isVagueImport(str) {
Copy link
Member

Choose a reason for hiding this comment

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

It isn't really vague, it's more about the fact that it is a direct ancestor.

create(context) {
return {
ImportDeclaration(node) {
const pathParts = node.source.value.split('/');
Copy link
Member

Choose a reason for hiding this comment

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

Use path.sep

return str === '' || str === '.' || str === '..';
}

return basename(str, extname(str)) === 'index';
Copy link
Member

Choose a reason for hiding this comment

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

I think you are better off resolving the path and then checking that either it is a directory and an ancestor of the current path, or it is an index file of such a directory. This prevents potential issues with this method, as this incorrectly warns on some weirder import paths that we'd still consider technically valid

Copy link
Contributor

@ismail-syed ismail-syed Aug 29, 2018

Choose a reason for hiding this comment

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

some weirder import paths that we'd still consider technically valid

What would some of these cases be? It would be good to add them to the tests

},
],

invalid: [
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add a few valid and invalid tests for importing non-default exports
eg. import {Foo, Bar} from '../'

CHANGELOG.md Outdated
@@ -14,6 +14,7 @@
### Added
* `shopify/prefer-singular-enums` ([#132](https://github.com/Shopify/eslint-plugin-shopify/pull/132))
* `shopify/react-no-multiple-render-methods` ([#134](https://github.com/Shopify/eslint-plugin-shopify/pull/134))
* `shopify/prefer-explicit-local-imports` ([#149](https://github.com/Shopify/eslint-plugin-shopify/pull/149))
Copy link
Contributor

Choose a reason for hiding this comment

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

shopify/prefer-namespaced-imports might be a better name - not entirely sure.

Copy link
Contributor

@ismail-syed ismail-syed left a comment

Choose a reason for hiding this comment

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

👍 Nice one. Nothing major from my end, just a couple comments.

@cartogram cartogram force-pushed the prefer-explicit-relative-imports branch 5 times, most recently from 8f22080 to 1723535 Compare September 30, 2018 21:57
@cartogram cartogram changed the title Adds prefer-explicit-local-imports rule Adds no-ancestor-directory-import rule Sep 30, 2018
@cartogram
Copy link
Contributor Author

cartogram commented Sep 30, 2018

@lemonmade ready for another look. Thanks!

cc/ @BPScott since you ran into this recently.

Copy link
Member

@BPScott BPScott left a comment

Choose a reason for hiding this comment

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

Nice. A few more test cases around components reaching into sibling components, and subcomponents would be handy. If I've understood the purpose of this PR then the following should all pass:

{
    code: "import Bar from '../Bar'",
    filename: fixtureFile('basic-app/app/components/Foo/Foo.js'),
},
{
    code: "import Bar from '..'",
    filename: fixtureFile('basic-app/app/components/Foo/Foo.js'),
},
{
    code: "import Bar from '../Bar'",
    filename: fixtureFile('basic-app/app/components/Foo/components/Baz/Baz.js'),
},
{
    code: "import Qux from '..'",
    filename: fixtureFile('basic-app/app/components/Foo/components/Baz/Baz.js'),
},
{
    code: "import Qux from '../Qux'",
    filename: fixtureFile('basic-app/app/components/Foo/components/Baz/Baz.js'),
},
{
    code: "import Bar from '../../../Bar'",
    filename: fixtureFile('basic-app/app/components/Foo/components/Baz/Baz.js'),
},
{
    code: "import Bar from '../../..'",
    filename: fixtureFile('basic-app/app/components/Foo/components/Baz/Baz.js'),
},

const {fixtureFile} = require('../../utilities');
const rule = require('../../../lib/rules/no-ancestor-directory-import');

const ruleTester = new RuleTester();
Copy link
Member

Choose a reason for hiding this comment

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

I think you can do

const parserOptions =
new RuleTester({parserOptions:  {
  ecmaVersion: 6,
  sourceType: 'module',
}})

to avoid having to pass parserOptions into every valid/invalid block below. (see https://eslint.org/docs/developer-guide/nodejs-api#ruletester)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TIL! Thanks @BPScott

@@ -0,0 +1,27 @@
# Prefer imports from within a directory extend to the file from where they are importing without relying on an index file. (no-ancestor-directory-import)
Copy link
Member

Choose a reason for hiding this comment

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

Prefer that

meta: {
docs: {
description:
'Prefer imports from within a directory extend to the file from where they are importing without relying on an index file.',
Copy link
Member

Choose a reason for hiding this comment

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

Here too

docs: {
description:
'Prefer imports from within a directory extend to the file from where they are importing without relying on an index file.',
category: 'Best Practises',
Copy link
Member

Choose a reason for hiding this comment

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

Best practices

fixable: null,
},
create(context) {
function isAncestorDirectoryImport(resolvedSource) {
Copy link
Member

Choose a reason for hiding this comment

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

This function doesn't seem to quite line up with what it checks

@cartogram cartogram force-pushed the prefer-explicit-relative-imports branch 4 times, most recently from e417285 to e820e7a Compare October 2, 2018 02:29
@@ -0,0 +1,27 @@
# Prefer that imports from within a directory extend to the file from where they are importing without relying on an index file. (no-ancestor-directory-import)

Imports inside the same directory should extend directly to the file from where they are importing without relying on an index file. This means the source of these imports should not end with a directory (`/`), but the path should terminate at an individual filename. This preserves the index file inside a directory as a mechanism for exposing pieces of the module to the outside application.
Copy link
Member

Choose a reason for hiding this comment

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

The last sentence should be augmented with , rather than as a way to export the parts that the module internally depends on. or something like that.

context.report({
node,
message:
'Relative local imports should extend to the file from where they are importing without relying on an index file.',
Copy link
Member

Choose a reason for hiding this comment

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

I don't know if this message is quite right; since we resolve the source, it might not even be a relative import (i.e., something in app/sections asking for index would fail this rule, as that likely resolves to app/index.js

resolvedSource,
);

const parts = relativeDifference
Copy link
Member

Choose a reason for hiding this comment

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

So this just strips out all the leading ./../../ stuff right?

filename: fixtureFile('basic-app/app/components/Foo/Foo.js'),
},
{
code: "import Bar from '../../..'",
Copy link
Member

Choose a reason for hiding this comment

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

Might want to check that ../../../ works also (trailing slash)

@cartogram cartogram force-pushed the prefer-explicit-relative-imports branch 3 times, most recently from ecce01b to e257b2d Compare October 15, 2018 14:25
@cartogram cartogram force-pushed the prefer-explicit-relative-imports branch 2 times, most recently from 9434d5b to 7b8a75a Compare October 27, 2018 20:04
@cartogram cartogram force-pushed the prefer-explicit-relative-imports branch from 7b8a75a to 414db1d Compare October 27, 2018 20:06
@cartogram cartogram merged commit fede0a0 into master Oct 27, 2018
@cartogram cartogram deleted the prefer-explicit-relative-imports branch October 27, 2018 20:08
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants