Skip to content
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

feat(typescript-estree): add parserOption to turn on debug logs #1413

Merged
merged 6 commits into from Jan 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -22,7 +22,7 @@
"cz": "git-cz",
"check:docs": "lerna run check:docs",
"check:configs": "lerna run check:configs",
"check:spelling": "cspell --config=.cspell.json **/*.{md,ts,js}",
"check:spelling": "cspell --config=.cspell.json \"**/*.{md,ts,js}\"",
"generate-contributors": "yarn ts-node --transpile-only ./tools/generate-contributors.ts && yarn all-contributors generate",
"format": "prettier --write \"./**/*.{ts,js,json,md}\"",
"format-check": "prettier --list-different \"./**/*.{ts,js,json,md}\"",
Expand Down
3 changes: 3 additions & 0 deletions packages/experimental-utils/src/ts-eslint/ParserOptions.ts
@@ -1,3 +1,5 @@
import { TSESTreeOptions } from '@typescript-eslint/typescript-estree';

export interface ParserOptions {
comment?: boolean;
ecmaFeatures?: {
Expand All @@ -9,6 +11,7 @@ export interface ParserOptions {
errorOnUnknownASTType?: boolean;
extraFileExtensions?: string[];
// ts-estree specific
debugLevel?: TSESTreeOptions['debugLevel'];
filePath?: string;
loc?: boolean;
noWatch?: boolean;
Expand Down
209 changes: 160 additions & 49 deletions packages/typescript-estree/README.md
Expand Up @@ -29,54 +29,140 @@ yarn add -D @typescript-eslint/typescript-estree

## API

### parse(code, options)
### Parsing

Parses the given string of code with the options provided and returns an ESTree-compatible AST. The options object has the following properties:
#### `parse(code, options)`

```js
{
// attach range information to each node
range: false,
Parses the given string of code with the options provided and returns an ESTree-compatible AST.

// attach line/column location information to each node
loc: false,
```ts
interface ParseOptions {
/**
* create a top-level comments array containing all comments
*/
comment?: boolean;

// create a top-level tokens array containing all tokens
tokens: false,
/**
* An array of modules to turn explicit debugging on for.
* - 'typescript-eslint' is the same as setting the env var `DEBUG=typescript-eslint:*`
* - 'eslint' is the same as setting the env var `DEBUG=eslint:*`
* - 'typescript' is the same as setting `extendedDiagnostics: true` in your tsconfig compilerOptions
*
* For convenience, also supports a boolean:
* - true === ['typescript-eslint']
* - false === []
*/
debugLevel?: boolean | ('typescript-eslint' | 'eslint' | 'typescript')[];

// create a top-level comments array containing all comments
comment: false,
/**
* Cause the parser to error if it encounters an unknown AST node type (useful for testing).
* This case only usually occurs when TypeScript releases new features.
*/
errorOnUnknownASTType?: boolean;
armano2 marked this conversation as resolved.
Show resolved Hide resolved

/*
* enable parsing JSX. For more details, see https://www.typescriptlang.org/docs/handbook/jsx.html
/**
* The absolute path to the file being parsed.
Copy link
Member

Choose a reason for hiding this comment

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

this is not fully true anymore, relative paths are working to they are converted to cwd + path

*/
filePath?: string;

/**
* Enable parsing of JSX.
* For more details, see https://www.typescriptlang.org/docs/handbook/jsx.html
*
* NOTE: this setting does not effect known file types (.js, .jsx, .ts, .tsx, .json) because the
* TypeScript compiler has its own internal handling for known file extensions.
*
* Exact behaviour:
* - .js, .jsx, .tsx files are parsed as if this is true
* - .ts files are parsed as if this is false
* - unknown extensions (.md, .vue) will respect this setting
* For the exact behavior, see https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser#parseroptionsecmafeaturesjsx
*/
jsx: false,
jsx?: boolean;

/**
* Controls whether the `loc` information to each node.
* The `loc` property is an object which contains the exact line/column the node starts/ends on.
* This is similar to the `range` property, except it is line/column relative.
*/
loc?: boolean;

/*
* Allows overriding of function used for logging.
* When value is `false`, no logging will occur.
* When value is not provided, `console.log()` will be used.
*/
loggerFn?: Function | false;

/**
* Controls whether the `range` property is included on AST nodes.
* The `range` property is a [number, number] which indicates the start/end index of the node in the file contents.
* This is similar to the `loc` property, except this is the absolute index.
*/
range?: boolean;

/**
* Set to true to create a top-level array containing all tokens from the file.
*/
tokens?: boolean;

/*
* The JSX AST changed the node type for string literals
* inside a JSX Element from `Literal` to `JSXText`.
* When value is `true`, these nodes will be parsed as type `JSXText`.
* When value is `false`, these nodes will be parsed as type `Literal`.
*/
useJSXTextNode: false,
useJSXTextNode?: boolean;
}

// Cause the parser to error if it encounters an unknown AST node type (useful for testing)
const PARSE_DEFAULT_OPTIONS: ParseOptions = {
comment: false,
errorOnUnknownASTType: false,
filePath: 'estree.ts', // or 'estree.tsx', if you pass jsx: true
jsx: false,
loc: false,
loggerFn: undefined,
range: false,
tokens: false,
useJSXTextNode: false,
};

/*
* Allows overriding of function used for logging.
* When value is `false`, no logging will occur.
* When value is not provided, `console.log()` will be used.
declare function parse(
code: string,
options: ParseOptions = PARSE_DEFAULT_OPTIONS,
): TSESTree.Program;
```

Example usage:

```js
import { parse } from '@typescript-eslint/typescript-estree';

const code = `const hello: string = 'world';`;
const ast = parse(code, {
loc: true,
range: true,
});
```

#### `parseAndGenerateServices(code, options)`

Parses the given string of code with the options provided and returns an ESTree-compatible AST. Accepts additional options which can be used to generate type information along with the AST.

```ts
interface ParseAndGenerateServicesOptions extends ParseOptions {
/**
* Causes the parser to error if the TypeScript compiler returns any unexpected syntax/semantic errors.
*/
loggerFn: undefined,
errorOnTypeScriptSyntacticAndSemanticIssues?: boolean;

/**
* When `project` is provided, this controls the non-standard file extensions which will be parsed.
* It accepts an array of file extensions, each preceded by a `.`.
*/
extraFileExtensions?: string[];

/**
* The absolute path to the file being parsed.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* The absolute path to the file being parsed.
* Absolute (or relative to `tsconfigRootDir`) path to the file being parsed.

* When `project` is provided, this is required, as it is used to fetch the file from the TypeScript compiler's cache.
*/
filePath?: string;

/**
* Allows the user to control whether or not two-way AST node maps are preserved
Expand All @@ -88,42 +174,67 @@ Parses the given string of code with the options provided and returns an ESTree-
* NOTE: If `preserveNodeMaps` is explicitly set by the user, it will be respected,
* regardless of whether or not `project` is in use.
*/
preserveNodeMaps: undefined
preserveNodeMaps?: boolean;

/**
* Absolute (or relative to `tsconfigRootDir`) paths to the tsconfig(s).
* If this is provided, type information will be returned.
*/
project?: string | string[];

/**
* The absolute path to the root directory for all provided `project`s.
*/
tsconfigRootDir?: string;

/**
***************************************************************************************
* IT IS RECOMMENDED THAT YOU DO NOT USE THIS OPTION, AS IT CAUSES PERFORMANCE ISSUES. *
***************************************************************************************
*
* When passed with `project`, this allows the parser to create a catch-all, default program.
* This means that if the parser encounters a file not included in any of the provided `project`s,
* it will not error, but will instead parse the file and its dependencies in a new program.
*/
createDefaultProgram?: boolean;
}

const PARSE_AND_GENERATE_SERVICES_DEFAULT_OPTIONS: ParseOptions = {
...PARSE_DEFAULT_OPTIONS,
errorOnTypeScriptSyntacticAndSemanticIssues: false,
extraFileExtensions: [],
preserveNodeMaps: false, // or true, if you do not set this, but pass `project`
project: undefined,
tsconfigRootDir: process.cwd(),
};

declare function parseAndGenerateServices(
code: string,
options: ParseOptions = PARSE_DEFAULT_OPTIONS,
): TSESTree.Program;
```

Example usage:

```js
const parser = require('@typescript-eslint/typescript-estree');
import { parseAndGenerateServices } from '@typescript-eslint/typescript-estree';

const code = `const hello: string = 'world';`;
const ast = parser.parse(code, {
range: true,
const ast = parseAndGenerateServices(code, {
filePath: '/some/path/to/file/foo.ts',
loc: true,
project: './tsconfig.json',
range: true,
});
```

### version
### `TSESTree`, `AST_NODE_TYPES` and `AST_TOKEN_TYPES`

Exposes the current version of `typescript-estree` as specified in `package.json`.
Types for the AST produced by the parse functions.

Example usage:

```js
const parser = require('@typescript-eslint/typescript-estree');
const version = parser.version;
```

### `AST_NODE_TYPES`

Exposes an object that contains the AST node types produced by the parser.

Example usage:

```js
const parser = require('@typescript-eslint/typescript-estree');
const astNodeTypes = parser.AST_NODE_TYPES;
```
- `TSESTree` is a namespace which contains object types representing all of the AST Nodes produced by the parser.
- `AST_NODE_TYPES` is an enum which provides the values for every single AST node's `type` property.
- `AST_TOKEN_TYPES` is an enum which provides the values for every single AST token's `type` property.

## Supported TypeScript Version

Expand Down
Expand Up @@ -3,9 +3,9 @@ import path from 'path';
import * as ts from 'typescript';
import { Extra } from '../parser-options';
import {
getTsconfigPath,
DEFAULT_COMPILER_OPTIONS,
ASTAndProgram,
getTsconfigPath,
createDefaultCompilerOptionsFromExtra,
} from './shared';

const log = debug('typescript-eslint:typescript-estree:createDefaultProgram');
Expand All @@ -31,7 +31,7 @@ function createDefaultProgram(

const commandLine = ts.getParsedCommandLineOfConfigFile(
tsconfigPath,
DEFAULT_COMPILER_OPTIONS,
createDefaultCompilerOptionsFromExtra(extra),
{ ...ts.sys, onUnRecoverableConfigFileDiagnostic: () => {} },
);

Expand Down
Expand Up @@ -3,7 +3,7 @@ import * as ts from 'typescript';
import { Extra } from '../parser-options';
import {
ASTAndProgram,
DEFAULT_COMPILER_OPTIONS,
createDefaultCompilerOptionsFromExtra,
getScriptKind,
} from './shared';

Expand Down Expand Up @@ -67,7 +67,7 @@ function createIsolatedProgram(code: string, extra: Extra): ASTAndProgram {
noResolve: true,
target: ts.ScriptTarget.Latest,
jsx: extra.jsx ? ts.JsxEmit.Preserve : undefined,
...DEFAULT_COMPILER_OPTIONS,
...createDefaultCompilerOptionsFromExtra(extra),
},
compilerHost,
);
Expand Down
Expand Up @@ -6,9 +6,9 @@ import { WatchCompilerHostOfConfigFile } from './WatchCompilerHostOfConfigFile';
import {
canonicalDirname,
CanonicalPath,
getTsconfigPath,
DEFAULT_COMPILER_OPTIONS,
createDefaultCompilerOptionsFromExtra,
getCanonicalFileName,
getTsconfigPath,
} from './shared';

const log = debug('typescript-eslint:typescript-estree:createWatchProgram');
Expand Down Expand Up @@ -233,7 +233,7 @@ function createWatchProgram(
// create compiler host
const watchCompilerHost = ts.createWatchCompilerHost(
tsconfigPath,
DEFAULT_COMPILER_OPTIONS,
createDefaultCompilerOptionsFromExtra(extra),
ts.sys,
ts.createSemanticDiagnosticsBuilderProgram,
diagnosticReporter,
Expand Down
15 changes: 14 additions & 1 deletion packages/typescript-estree/src/create-program/shared.ts
Expand Up @@ -20,6 +20,19 @@ const DEFAULT_COMPILER_OPTIONS: ts.CompilerOptions = {
noUnusedParameters: true,
};

function createDefaultCompilerOptionsFromExtra(
extra: Extra,
): ts.CompilerOptions {
if (extra.debugLevel.has('typescript')) {
return {
...DEFAULT_COMPILER_OPTIONS,
extendedDiagnostics: true,
};
}

return DEFAULT_COMPILER_OPTIONS;
}

// This narrows the type so we can be sure we're passing canonical names in the correct places
type CanonicalPath = string & { __brand: unknown };

Expand Down Expand Up @@ -85,7 +98,7 @@ export {
ASTAndProgram,
canonicalDirname,
CanonicalPath,
DEFAULT_COMPILER_OPTIONS,
createDefaultCompilerOptionsFromExtra,
ensureAbsolutePath,
getCanonicalFileName,
getScriptKind,
Expand Down