Skip to content
Permalink
Browse files

feat(experimental-utils): expose ast utility functions (#1670)

  • Loading branch information
bradzacher committed Mar 20, 2020
1 parent 2b9603d commit 3eb5d4525e95c8ab990f55588b8d830a02ce5a9c
Showing with 835 additions and 537 deletions.
  1. +2 −1 .cspell.json
  2. +0 −1 packages/eslint-plugin/package.json
  3. +6 −2 packages/eslint-plugin/src/rules/comma-spacing.ts
  4. +2 −3 packages/eslint-plugin/src/rules/func-call-spacing.ts
  5. +8 −5 packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts
  6. +1 −1 packages/eslint-plugin/src/rules/no-array-constructor.ts
  7. +1 −2 packages/eslint-plugin/src/rules/prefer-includes.ts
  8. +1 −2 packages/eslint-plugin/src/rules/prefer-optional-chain.ts
  9. +6 −2 packages/eslint-plugin/src/rules/prefer-regexp-exec.ts
  10. +5 −3 packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts
  11. +4 −9 packages/eslint-plugin/src/rules/require-await.ts
  12. +2 −3 packages/eslint-plugin/src/rules/space-before-function-paren.ts
  13. +3 −2 packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts
  14. +2 −265 packages/eslint-plugin/src/util/astUtils.ts
  15. +2 −3 packages/eslint-plugin/src/util/misc.ts
  16. +0 −180 packages/eslint-plugin/typings/eslint-utils.d.ts
  17. +13 −10 packages/experimental-utils/README.md
  18. +2 −1 packages/experimental-utils/package.json
  19. +56 −0 packages/experimental-utils/src/ast-utils/eslint-utils/PatternMatcher.ts
  20. +94 −0 packages/experimental-utils/src/ast-utils/eslint-utils/ReferenceTracker.ts
  21. +127 −0 packages/experimental-utils/src/ast-utils/eslint-utils/astUtilities.ts
  22. +5 −0 packages/experimental-utils/src/ast-utils/eslint-utils/index.ts
  23. +106 −0 packages/experimental-utils/src/ast-utils/eslint-utils/predicates.ts
  24. +27 −0 packages/experimental-utils/src/ast-utils/eslint-utils/scopeAnalysis.ts
  25. +3 −0 packages/experimental-utils/src/ast-utils/index.ts
  26. +15 −0 packages/experimental-utils/src/ast-utils/misc.ts
  27. +247 −0 packages/experimental-utils/src/ast-utils/predicates.ts
  28. +3 −1 packages/experimental-utils/src/eslint-utils/RuleCreator.ts
  29. +3 −1 packages/experimental-utils/src/eslint-utils/applyDefault.ts
  30. +3 −1 packages/experimental-utils/src/eslint-utils/deepMerge.ts
  31. +5 −2 packages/experimental-utils/src/eslint-utils/getParserServices.ts
  32. +4 −15 packages/experimental-utils/src/index.ts
  33. +1 −1 packages/experimental-utils/src/ts-eslint-scope/Definition.ts
  34. +1 −1 packages/experimental-utils/src/ts-eslint-scope/Options.ts
  35. +1 −1 packages/experimental-utils/src/ts-eslint-scope/PatternVisitor.ts
  36. +1 −1 packages/experimental-utils/src/ts-eslint-scope/Reference.ts
  37. +1 −1 packages/experimental-utils/src/ts-eslint-scope/Referencer.ts
  38. +1 −1 packages/experimental-utils/src/ts-eslint-scope/Scope.ts
  39. +1 −1 packages/experimental-utils/src/ts-eslint-scope/ScopeManager.ts
  40. +1 −1 packages/experimental-utils/src/ts-eslint-scope/Variable.ts
  41. +1 −4 packages/experimental-utils/src/ts-eslint/AST.ts
  42. +1 −1 packages/experimental-utils/src/ts-eslint/Linter.ts
  43. +3 −1 packages/experimental-utils/src/ts-eslint/ParserOptions.ts
  44. +1 −1 packages/experimental-utils/src/ts-eslint/Rule.ts
  45. +1 −4 packages/experimental-utils/src/ts-eslint/RuleTester.ts
  46. +1 −1 packages/experimental-utils/src/ts-eslint/Scope.ts
  47. +2 −2 packages/experimental-utils/src/ts-eslint/SourceCode.ts
  48. +12 −0 packages/experimental-utils/src/ts-estree.ts
  49. +40 −0 packages/experimental-utils/typings/eslint-utils.d.ts
  50. +7 −0 yarn.lock
@@ -10,7 +10,8 @@
"**/**/CONTRIBUTORS.md",
"**/**/ROADMAP.md",
"**/*.{json,snap}",
".cspell.json"
".cspell.json",
"yarn.lock"
],
"dictionaries": [
"typescript",
@@ -42,7 +42,6 @@
},
"dependencies": {
"@typescript-eslint/experimental-utils": "2.24.0",
"eslint-utils": "^1.4.3",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^3.0.0",
"tsutils": "^3.17.1"
@@ -2,8 +2,12 @@ import {
TSESTree,
AST_TOKEN_TYPES,
} from '@typescript-eslint/experimental-utils';
import { isClosingParenToken, isCommaToken } from 'eslint-utils';
import { isTokenOnSameLine, createRule } from '../util';
import {
isClosingParenToken,
isCommaToken,
isTokenOnSameLine,
createRule,
} from '../util';

type Options = [
{
@@ -1,5 +1,4 @@
import { TSESTree } from '@typescript-eslint/experimental-utils';
import { isOpeningParenToken } from 'eslint-utils';
import * as util from '../util';

export type Options = [
@@ -79,7 +78,7 @@ export default util.createRule<Options, MessageIds>({
| TSESTree.OptionalCallExpression
| TSESTree.NewExpression,
): void {
const isOptionalCall = util.isOptionalOptionalChain(node);
const isOptionalCall = util.isOptionalOptionalCallExpression(node);

const closingParenToken = sourceCode.getLastToken(node)!;
const lastCalleeTokenWithoutPossibleParens = sourceCode.getLastToken(
@@ -88,7 +87,7 @@ export default util.createRule<Options, MessageIds>({
const openingParenToken = sourceCode.getFirstTokenBetween(
lastCalleeTokenWithoutPossibleParens,
closingParenToken,
isOpeningParenToken,
util.isOpeningParenToken,
);
if (!openingParenToken || openingParenToken.range[1] >= node.range[1]) {
// new expression with no parens...
@@ -8,7 +8,13 @@ import {
TSESLint,
TSESTree,
} from '@typescript-eslint/experimental-utils';

import { TokenOrComment } from './BinarySearchTree';
import { OffsetStorage } from './OffsetStorage';
import { TokenInfo } from './TokenInfo';
import {
createRule,
ExcludeKeys,
isClosingBraceToken,
isClosingBracketToken,
isClosingParenToken,
@@ -19,11 +25,8 @@ import {
isOpeningBraceToken,
isOpeningParenToken,
isSemicolonToken,
} from 'eslint-utils';
import { TokenOrComment } from './BinarySearchTree';
import { OffsetStorage } from './OffsetStorage';
import { TokenInfo } from './TokenInfo';
import { createRule, ExcludeKeys, RequireKeys } from '../../util';
RequireKeys,
} from '../../util';

const GLOBAL_LINEBREAK_REGEX = /\r\n|[\r\n\u2028\u2029]/gu;
const WHITESPACE_REGEX = /\s*$/u;
@@ -37,7 +37,7 @@ export default util.createRule({
node.callee.type === AST_NODE_TYPES.Identifier &&
node.callee.name === 'Array' &&
!node.typeParameters &&
!util.isOptionalOptionalChain(node)
!util.isOptionalOptionalCallExpression(node)
) {
context.report({
node,
@@ -2,10 +2,9 @@ import {
AST_NODE_TYPES,
TSESTree,
} from '@typescript-eslint/experimental-utils';
import { getStaticValue } from 'eslint-utils';
import { AST as RegExpAST, parseRegExpLiteral } from 'regexpp';
import * as ts from 'typescript';
import { createRule, getParserServices } from '../util';
import { createRule, getParserServices, getStaticValue } from '../util';

export default createRule({
name: 'prefer-includes',
@@ -2,7 +2,6 @@ import {
AST_NODE_TYPES,
TSESTree,
} from '@typescript-eslint/experimental-utils';
import { isOpeningParenToken } from 'eslint-utils';
import * as util from '../util';

type ValidChainTarget =
@@ -203,7 +202,7 @@ export default util.createRule({
sourceCode.getFirstTokenBetween(
node.callee,
closingParenToken,
isOpeningParenToken,
util.isOpeningParenToken,
),
util.NullThrowsReasons.MissingToken('opening parenthesis', node.type),
);
@@ -1,6 +1,10 @@
import { TSESTree } from '@typescript-eslint/experimental-utils';
import { getStaticValue } from 'eslint-utils';
import { createRule, getParserServices, getTypeName } from '../util';
import {
createRule,
getParserServices,
getStaticValue,
getTypeName,
} from '../util';

export default createRule({
name: 'prefer-regexp-exec',
@@ -3,13 +3,15 @@ import {
TSESLint,
TSESTree,
} from '@typescript-eslint/experimental-utils';
import { AST as RegExpAST, RegExpParser } from 'regexpp';
import {
createRule,
getParserServices,
getPropertyName,
getStaticValue,
getTypeName,
isNotClosingParenToken,
} from 'eslint-utils';
import { AST as RegExpAST, RegExpParser } from 'regexpp';
import { createRule, getParserServices, getTypeName } from '../util';
} from '../util';

const EQ_OPERATORS = /^[=!]=/;
const regexpp = new RegExpParser();
@@ -3,11 +3,6 @@ import {
TSESLint,
TSESTree,
} from '@typescript-eslint/experimental-utils';
import {
isArrowToken,
getFunctionNameWithKind,
isOpeningParenToken,
} from 'eslint-utils';
import * as tsutils from 'tsutils';
import * as ts from 'typescript';
import * as util from '../util';
@@ -73,7 +68,7 @@ export default util.createRule({
loc: getFunctionHeadLoc(node, sourceCode),
messageId: 'missingAwait',
data: {
name: util.upperCaseFirst(getFunctionNameWithKind(node)),
name: util.upperCaseFirst(util.getFunctionNameWithKind(node)),
},
});
}
@@ -157,8 +152,8 @@ function getOpeningParenOfParams(
): TSESTree.Token {
return util.nullThrows(
node.id
? sourceCode.getTokenAfter(node.id, isOpeningParenToken)
: sourceCode.getFirstToken(node, isOpeningParenToken),
? sourceCode.getTokenAfter(node.id, util.isOpeningParenToken)
: sourceCode.getFirstToken(node, util.isOpeningParenToken),
util.NullThrowsReasons.MissingToken('(', node.type),
);
}
@@ -180,7 +175,7 @@ function getFunctionHeadLoc(

if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {
const arrowToken = util.nullThrows(
sourceCode.getTokenBefore(node.body, isArrowToken),
sourceCode.getTokenBefore(node.body, util.isArrowToken),
util.NullThrowsReasons.MissingToken('=>', node.type),
);

@@ -2,7 +2,6 @@ import {
AST_NODE_TYPES,
TSESTree,
} from '@typescript-eslint/experimental-utils';
import { isOpeningParenToken } from 'eslint-utils';
import * as util from '../util';

type Option = 'never' | 'always';
@@ -106,7 +105,7 @@ export default util.createRule<Options, MessageIds>({
// Always ignore non-async functions and arrow functions without parens, e.g. async foo => bar
if (
node.async &&
isOpeningParenToken(sourceCode.getFirstToken(node, { skip: 1 })!)
util.isOpeningParenToken(sourceCode.getFirstToken(node, { skip: 1 })!)
) {
return overrideConfig.asyncArrow ?? baseConfig;
}
@@ -143,7 +142,7 @@ export default util.createRule<Options, MessageIds>({
leftToken = sourceCode.getLastToken(node.typeParameters)!;
rightToken = sourceCode.getTokenAfter(leftToken)!;
} else {
rightToken = sourceCode.getFirstToken(node, isOpeningParenToken)!;
rightToken = sourceCode.getFirstToken(node, util.isOpeningParenToken)!;
leftToken = sourceCode.getTokenBefore(rightToken)!;
}
const hasSpacing = sourceCode.isSpaceBetweenTokens(leftToken, rightToken);
@@ -2,11 +2,12 @@ import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils';
import * as ts from 'typescript';
import {
createRule,
getParserServices,
getConstrainedTypeAtLocation,
getParserServices,
isClosingBraceToken,
isOpeningBraceToken,
} from '../util';
import { isTypeFlagSet, unionTypeParts } from 'tsutils';
import { isClosingBraceToken, isOpeningBraceToken } from 'eslint-utils';

export default createRule({
name: 'switch-exhaustiveness-check',

0 comments on commit 3eb5d45

Please sign in to comment.
You can’t perform that action at this time.