mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
117616: Ported alias-imports rule
This commit is contained in:
@@ -263,6 +263,7 @@
|
||||
"rxjs/no-nested-subscribe": "off", // todo: go over _all_ cases
|
||||
|
||||
// Custom DSpace Angular rules
|
||||
"dspace-angular-ts/alias-imports": "error",
|
||||
"dspace-angular-ts/themed-component-classes": "error",
|
||||
"dspace-angular-ts/themed-component-selectors": "error",
|
||||
"dspace-angular-ts/themed-component-usages": "error"
|
||||
|
@@ -1,6 +1,7 @@
|
||||
[DSpace ESLint plugins](../../../lint/README.md) > TypeScript rules
|
||||
_______
|
||||
|
||||
- [`dspace-angular-ts/alias-imports`](./rules/alias-imports.md): Unclear imports should be aliased for clarity
|
||||
- [`dspace-angular-ts/themed-component-classes`](./rules/themed-component-classes.md): Formatting rules for themeable component classes
|
||||
- [`dspace-angular-ts/themed-component-selectors`](./rules/themed-component-selectors.md): Themeable component selectors should follow the DSpace convention
|
||||
- [`dspace-angular-ts/themed-component-usages`](./rules/themed-component-usages.md): Themeable components should be used via their `ThemedComponent` wrapper class
|
||||
|
58
docs/lint/ts/rules/alias-imports.md
Normal file
58
docs/lint/ts/rules/alias-imports.md
Normal file
@@ -0,0 +1,58 @@
|
||||
[DSpace ESLint plugins](../../../../lint/README.md) > [TypeScript rules](../index.md) > `dspace-angular-ts/alias-imports`
|
||||
_______
|
||||
|
||||
Unclear imports should be aliased for clarity
|
||||
|
||||
_______
|
||||
|
||||
[Source code](../../../../lint/src/rules/ts/alias-imports.ts)
|
||||
|
||||
### Examples
|
||||
|
||||
|
||||
#### Valid code
|
||||
|
||||
##### correctly aliased imports
|
||||
|
||||
```typescript
|
||||
import { of as observableOf } from 'rxjs';
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
#### Invalid code & automatic fixes
|
||||
|
||||
##### imports without alias
|
||||
|
||||
```typescript
|
||||
import { of } from 'rxjs';
|
||||
```
|
||||
Will produce the following error(s):
|
||||
```
|
||||
This import must be aliased
|
||||
```
|
||||
|
||||
Result of `yarn lint --fix`:
|
||||
```typescript
|
||||
import { of as observableOf } from 'rxjs';
|
||||
```
|
||||
|
||||
|
||||
##### imports under the wrong alias
|
||||
|
||||
```typescript
|
||||
import { of as ofSomething } from 'rxjs';
|
||||
```
|
||||
Will produce the following error(s):
|
||||
```
|
||||
This import uses the wrong alias (should be {{ local }})
|
||||
```
|
||||
|
||||
Result of `yarn lint --fix`:
|
||||
```typescript
|
||||
import { of as observableOf } from 'rxjs';
|
||||
```
|
||||
|
||||
|
||||
|
132
lint/src/rules/ts/alias-imports.ts
Normal file
132
lint/src/rules/ts/alias-imports.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import {
|
||||
ESLintUtils,
|
||||
TSESLint,
|
||||
TSESTree,
|
||||
} from '@typescript-eslint/utils';
|
||||
|
||||
import {
|
||||
DSpaceESLintRuleInfo,
|
||||
NamedTests,
|
||||
} from '../../util/structure';
|
||||
|
||||
export enum Message {
|
||||
NO_ALIAS = 'noAlias',
|
||||
WRONG_ALIAS = 'wrongAlias',
|
||||
}
|
||||
|
||||
export const info: DSpaceESLintRuleInfo = {
|
||||
name: 'alias-imports',
|
||||
meta: {
|
||||
docs: {
|
||||
description: 'Unclear imports should be aliased for clarity',
|
||||
},
|
||||
messages: {
|
||||
[Message.NO_ALIAS]: 'This import must be aliased',
|
||||
[Message.WRONG_ALIAS]: 'This import uses the wrong alias (should be {{ local }})',
|
||||
},
|
||||
fixable: 'code',
|
||||
type: 'problem',
|
||||
schema: [
|
||||
{
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
package: { type: 'string' },
|
||||
imported: { type: 'string' },
|
||||
local: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
defaultOptions: [
|
||||
[
|
||||
{
|
||||
package: 'rxjs',
|
||||
imported: 'of',
|
||||
local: 'observableOf',
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
|
||||
export const rule = ESLintUtils.RuleCreator.withoutDocs({
|
||||
...info,
|
||||
create(context: TSESLint.RuleContext<Message, unknown[]>, options: any) {
|
||||
return options[0].reduce((selectors: any, option: any) => {
|
||||
selectors[`ImportDeclaration[source.value = "${option.package}"] > ImportSpecifier[imported.name = "${option.imported}"][local.name != "${option.local}"]`] = (node: TSESTree.ImportSpecifier) => handleUnaliasedImport(context, option, node);
|
||||
return selectors;
|
||||
}, {});
|
||||
},
|
||||
});
|
||||
|
||||
export const tests: NamedTests = {
|
||||
plugin: info.name,
|
||||
valid: [
|
||||
{
|
||||
name: 'correctly aliased imports',
|
||||
code: `
|
||||
import { of as observableOf } from 'rxjs';
|
||||
`,
|
||||
},
|
||||
],
|
||||
invalid: [
|
||||
{
|
||||
name: 'imports without alias',
|
||||
code: `
|
||||
import { of } from 'rxjs';
|
||||
`,
|
||||
errors: [
|
||||
{
|
||||
messageId: 'noAlias',
|
||||
},
|
||||
],
|
||||
output: `
|
||||
import { of as observableOf } from 'rxjs';
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: 'imports under the wrong alias',
|
||||
code: `
|
||||
import { of as ofSomething } from 'rxjs';
|
||||
`,
|
||||
errors: [
|
||||
{
|
||||
messageId: 'wrongAlias',
|
||||
},
|
||||
],
|
||||
output: `
|
||||
import { of as observableOf } from 'rxjs';
|
||||
`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* Replaces the incorrectly aliased imports with the ones defined in the defaultOptions
|
||||
*
|
||||
* @param context The current {@link TSESLint.RuleContext}
|
||||
* @param option The current `defaultOptions` that needs to be handled
|
||||
* @param node The incorrect import node that should be fixed
|
||||
*/
|
||||
function handleUnaliasedImport(context: TSESLint.RuleContext<Message, unknown[]>, option: any, node: TSESTree.ImportSpecifier): void {
|
||||
if (node.local.name === node.imported.name) {
|
||||
context.report({
|
||||
messageId: Message.NO_ALIAS,
|
||||
node: node,
|
||||
fix(fixer: TSESLint.RuleFixer) {
|
||||
return fixer.replaceText(node.local, `${option.imported} as ${option.local}`);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
context.report({
|
||||
messageId: Message.WRONG_ALIAS,
|
||||
data: { local: option.local },
|
||||
node: node,
|
||||
fix(fixer: TSESLint.RuleFixer) {
|
||||
return fixer.replaceText(node.local, option.local);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
@@ -10,11 +10,13 @@ import {
|
||||
RuleExports,
|
||||
} from '../../util/structure';
|
||||
/* eslint-disable import/no-namespace */
|
||||
import * as aliasImports from './alias-imports';
|
||||
import * as themedComponentClasses from './themed-component-classes';
|
||||
import * as themedComponentSelectors from './themed-component-selectors';
|
||||
import * as themedComponentUsages from './themed-component-usages';
|
||||
|
||||
const index = [
|
||||
aliasImports,
|
||||
themedComponentClasses,
|
||||
themedComponentSelectors,
|
||||
themedComponentUsages,
|
||||
|
Reference in New Issue
Block a user