Skip to content

Commit

Permalink
fix: imports order in .brs files stopped working (#8)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Changed order of imports
  • Loading branch information
bchelkowski authored Dec 21, 2021
1 parent 4a9e85e commit 374feaa
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 36 deletions.
78 changes: 73 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,24 +105,92 @@ A rule to use with [Kopytko Packager](https://github.com/getndazn/kopytko-packag
and [Kopytko Unit Testing Framework](https://github.com/getndazn/kopytko-unit-testing-framework) 's mocking mechanism.

Enforces a proper alphabetical and path-specific order of `@import` and `@mock` annotations:
- `@mock` annotations have to be after all `@import` annotations
- alphabetical order of paths
- nested paths have to be declared after their root path
1. imports or mocks from external packages have to be before local ones
2. `@mock` annotations have to be after all `@import` annotations
3. alphabetical order of external packages names
4. alphabetical order of paths
5. nested paths have to be declared after their root path

Examples of **incorrect** code for this rule:
#### External packages before local

Example of **incorrect** code:
```brightscript
' @import /components/main-function.brs
' @import /components/nested/another-function.brs
' @import /components/nested/cool-function.brs
' @import /components/nested/some-function.brs from package-name
' @mock /components/mocked-function.brs
' @mock /components/some-mocked-function.brs from package-name
```

Example of **correct** code:
```brightscript
' @import /components/nested/some-function.brs from package-name
' @mock /components/some-mocked-function.brs from package-name
' @import /components/main-function.brs
' @import /components/nested/another-function.brs
' @import /components/nested/cool-function.brs
' @mock /components/mocked-function.brs
```

#### Imports before mocks

Example of **incorrect** code:
```brightscript
' @mock /components/mocked-function.brs
' @import /components/main-function.brs
' @import /components/nested/another-function.brs
' @import /components/nested/cool-function.brs
```

Example of **correct** code:
```brightscript
' @import /components/main-function.brs
' @import /components/nested/another-function.brs
' @import /components/nested/cool-function.brs
' @mock /components/mocked-function.brs
```

#### Alphabetical order of external packages names

Example of **incorrect** code:
```brightscript
' @import /components/a-function.brs from package-name
' @import /components/some-function.brs from another-package-name
' @mock /components/another-mocked-function.brs from package-name
' @mock /components/some-mocked-function.brs from another-package-name
' @import /components/main-function.brs
' @mock /components/mocked-function.brs
```

Example of **correct** code:
```brightscript
' @import /components/some-function.brs from another-package-name
' @import /components/a-function.brs from package-name
' @mock /components/some-mocked-function.brs from another-package-name
' @mock /components/another-mocked-function.brs from package-name
' @import /components/main-function.brs
' @mock /components/mocked-function.brs
```

#### Alphabetical order of paths

Example of **incorrect** code:
```brightscript
' @import /components/nested/another-function.brs
' @import /components/main-function.brs
' @import /components/nested/cool-function.brs
' @mock /components/some-mocked-function.brs
' @mock /components/mocked-function.brs
```

Examples of **correct** code for this rule:
Example of **correct** code:
```brightscript
' @import /components/main-function.brs
' @import /components/nested/another-function.brs
' @import /components/nested/cool-function.brs
' @mock /components/mocked-function.brs
' @mock /components/some-mocked-function.brs
```


Expand Down
85 changes: 54 additions & 31 deletions src/rules/dependencies-order/checker.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
const { messageId } = require('./consts');

const IMPORT_DEFINITION_KEY = '@import';
const DEPENDENCY_URI_REGEX = /^@(import|mock)\s+(?:pkg:)?(\/[\w-/.]+\.brs)\s*$/;
const MOCK_DEFINITION_KEY = '@mock';
const DEPENDENCY_URI_REGEX = /^@(import|mock)\s+(?:pkg:)?(\/[\w-/.]+\.brs)\s*(?:(?:from\s+)([\w-@/.]+\s*))?$/;

module.exports = class DependenciesOrderChecker {
constructor(context) {
Expand All @@ -26,16 +24,34 @@ module.exports = class DependenciesOrderChecker {
if (line.type !== 'Comment') {
return dependencyEntries;
}
if (!line.value.includes(IMPORT_DEFINITION_KEY) && !line.value.includes(MOCK_DEFINITION_KEY)) {

const dependency = this._getDependency(line.value)
if (!dependency) {
return dependencyEntries;
}

dependencyEntries.push(line.value);
dependencyEntries.push(dependency);
}

return dependencyEntries;
}

_getDependency(dependencyText) {
const parts = dependencyText.match(DEPENDENCY_URI_REGEX);

if (parts) {
const [_, definitionKey, filePath, packageName] = parts;

return {
definitionKey,
filePath,
packageName,
};
}

return parts;
}

_reportViolation(node) {
this.context.report({
messageId,
Expand All @@ -45,38 +61,45 @@ module.exports = class DependenciesOrderChecker {

_sortDependencies(dependencies) {
dependencies.sort((a, b) => {
const isAMock = a.includes(MOCK_DEFINITION_KEY);
const isBMock = b.includes(MOCK_DEFINITION_KEY);

if (isAMock !== isBMock) {
return isAMock ? 1 : -1;
if (a.packageName !== b.packageName && (!a.packageName || !b.packageName)) {
return this._moveExternalDependenciesBeforeLocal(a.packageName, b.packageName);
}

const aUri = (a.match(DEPENDENCY_URI_REGEX) || [''])[0];
const bUri = (b.match(DEPENDENCY_URI_REGEX) || [''])[0];

const aParts = aUri.split('/');
const bParts = bUri.split('/');

let i = 0;
while (aParts[i]) {
const aPart = aParts[i];
const bPart = bParts[i];

if (aPart === bPart) {
i++;
} else {
if (aParts[i+1] && !bParts[i+1]) {
return 1;
} else if (!aParts[i+1] && bParts[i+1]) {
return -1;
}
if (a.definitionKey !== b.definitionKey) {
return this._orderDefinitionKeysAlphabetically(a.definitionKey, b.definitionKey);
}

return a.toLowerCase().localeCompare(b.toLowerCase());
}
if (a.packageName !== b.packageName) {
return this._orderPackageNamesAlphabetically(a.packageName, b.packageName);
}

return this._orderFileNamesAlphabetically(a.filePath, b.filePath);
});

return dependencies;
}

_moveExternalDependenciesBeforeLocal(packageNameA, packageNameB) {
if (!packageNameA) {
return 1;
}

if (!packageNameB) {
return -1;
}

return 1;
}

_orderDefinitionKeysAlphabetically(definitionKeyA, definitionKeyB) {
return definitionKeyA.localeCompare(definitionKeyB);
}

_orderPackageNamesAlphabetically(packageNameA, packageNameB) {
return packageNameA.localeCompare(packageNameB);
}

_orderFileNamesAlphabetically(filePathA, filePathB) {
return filePathA.toLowerCase().localeCompare(filePathB.toLowerCase());
}
}

0 comments on commit 374feaa

Please sign in to comment.