Skip to content

Commit

Permalink
Partially support babel parser (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
seiyab authored Nov 21, 2023
1 parent 55d5884 commit a9b848f
Show file tree
Hide file tree
Showing 15 changed files with 305 additions and 111 deletions.
12 changes: 5 additions & 7 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { printers as estreePrinters } from "prettier/plugins/estree";
import { preprocess as p } from "./lib/preprocess";
export { parsers } from "prettier/plugins/typescript";
import { AST } from "prettier";

export const printers = {
estree: {
...estreePrinters.estree,
preprocess: p,
},
};
const originalPreprocess = estreePrinters.estree.preprocess ?? ((x: AST) => x);

estreePrinters.estree.preprocess = (x, options) =>
p(originalPreprocess(x, options));
68 changes: 67 additions & 1 deletion lib/ast/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,72 @@
import { AST_NODE_TYPES } from "@typescript-eslint/types";
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";

export const functionExpressions = [
AST_NODE_TYPES.FunctionExpression,
AST_NODE_TYPES.ArrowFunctionExpression,
];

export type NodeTypes = AST_NODE_TYPES | BabelNodeTypes;
export type Node<T extends NodeTypes = NodeTypes> = (
| TSESTree.Node
| BabelNode
) & {
type: T;
};

// --- babel specific nodes
export enum BabelNodeTypes {
ClassProperty = "ClassProperty",
ClassPrivateProperty = "ClassPrivateProperty",
ClassMethod = "ClassMethod",
ClassPrivateMethod = "ClassPrivateMethod",
TSDeclareMethod = "TSDeclareMethod",
PrivateName = "PrivateName",
File = "File",
}
// type BabelNodeTypes = (typeof BabelNodeTypes)[keyof typeof BabelNodeTypes];

type BabelNode =
| ClassProperty
| ClassPrivateProperty
| ClassMethod
| ClassPrivateMethod
| TSDeclareMethod
| PrivateName
| File;

type ClassProperty = Override<
TSESTree.PropertyDefinition,
{ type: BabelNodeTypes.ClassProperty; abstract: boolean; key: Node }
>;

type ClassPrivateProperty = Override<
ClassProperty,
{ type: BabelNodeTypes.ClassPrivateProperty }
>;

type ClassMethod = Override<
TSESTree.MethodDefinition,
{ type: BabelNodeTypes.ClassMethod; key: Node }
>;

type ClassPrivateMethod = Override<
ClassMethod,
{ type: BabelNodeTypes.ClassPrivateMethod }
>;

type TSDeclareMethod = Override<
TSESTree.TSAbstractMethodDefinition,
{ type: BabelNodeTypes.TSDeclareMethod; abstract: boolean; key: Node }
>;

type PrivateName = {
type: BabelNodeTypes.PrivateName;
id: Node;
};

type File = {
type: BabelNodeTypes.File;
program: Node;
};

type Override<T, U> = Omit<T, keyof U> & U;
8 changes: 6 additions & 2 deletions lib/comparator/abstracted.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
import { AST_NODE_TYPES } from "@typescript-eslint/types";
import { BabelNodeTypes, Node } from "../ast";

export function abstracted(node: TSESTree.Node): boolean {
export function abstracted(node: Node): boolean {
switch (node.type) {
case AST_NODE_TYPES.TSAbstractPropertyDefinition:
case AST_NODE_TYPES.TSAbstractMethodDefinition:
return true;
case BabelNodeTypes.ClassProperty:
case BabelNodeTypes.TSDeclareMethod:
return node.abstract === true;
}
return false;
}
16 changes: 10 additions & 6 deletions lib/comparator/accessibility.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
import { C, Comparator } from "./comparator";
import { BabelNodeTypes, Node } from "../ast";

export function accessibility<T extends TSESTree.Node>(): Comparator<T> {
export function accessibility<T extends Node>(): Comparator<T> {
return C.by(($) => {
if ("accessibility" in $) {
switch ($.accessibility) {
Expand All @@ -13,11 +14,14 @@ export function accessibility<T extends TSESTree.Node>(): Comparator<T> {
return 2;
}
}
if (
$.type === AST_NODE_TYPES.PropertyDefinition ||
$.type === AST_NODE_TYPES.MethodDefinition
) {
if ($.key.type === AST_NODE_TYPES.PrivateIdentifier) return 3;
switch ($.type) {
case AST_NODE_TYPES.PropertyDefinition:
case AST_NODE_TYPES.MethodDefinition:
if ($.key.type === AST_NODE_TYPES.PrivateIdentifier) return 3;
break;
case BabelNodeTypes.ClassPrivateMethod:
case BabelNodeTypes.ClassPrivateProperty:
return 3;
}
return 0;
}, C.number);
Expand Down
12 changes: 6 additions & 6 deletions lib/comparator/comparator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ export const C = {
return Order.Equal;
},
defer(a: boolean, b: boolean): Order {
if (a === b) return Order.Equal;
if (a) return Order.Greater;
if (!!a === !!b) return Order.Equal;
if (!!a) return Order.Greater;
return Order.Less;
},
prefer(a: boolean, b: boolean): Order {
if (a === b) return Order.Equal;
if (a) return Order.Less;
if (!!a === !!b) return Order.Equal;
if (!!a) return Order.Less;
return Order.Greater;
},
string(a: string, b: string): Order {
Expand All @@ -57,9 +57,9 @@ export const C = {
return (a, b) => {
if (a == null) {
if (b == null) return Order.Equal;
return Order.Less;
return Order.Greater;
}
if (b == null) return Order.Greater;
if (b == null) return Order.Less;
return comp(a, b);
};
},
Expand Down
5 changes: 3 additions & 2 deletions lib/comparator/decorated.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
import { AST_NODE_TYPES } from "@typescript-eslint/types";
import { Node } from "../ast";

export function decorated(node: TSESTree.Node): boolean {
export function decorated(node: Node): boolean {
switch (node.type) {
case AST_NODE_TYPES.PropertyDefinition:
case AST_NODE_TYPES.MethodDefinition:
Expand Down
82 changes: 48 additions & 34 deletions lib/comparator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
import { C } from "./comparator";
import { select } from "./select";
import { keyIdentifierName } from "./key-identifier-name";
import { functionExpressions } from "../ast";
import { BabelNodeTypes, Node, functionExpressions } from "../ast";
import { accessibility } from "./accessibility";
import { decorated } from "./decorated";
import { abstracted } from "./abstracted";
import { methodKind } from "./method-kind";

export const comparator = C.chain<TSESTree.Node>(
export const comparator = C.chain<Node>(
// Signature
C.capture(
select.node(AST_NODE_TYPES.TSIndexSignature),
Expand All @@ -17,24 +17,28 @@ export const comparator = C.chain<TSESTree.Node>(

// field
C.capture(
select.or(
select.and(
select.node(AST_NODE_TYPES.TSPropertySignature),
select.not(functionSignature),
),
select.and(
select.node(
AST_NODE_TYPES.PropertyDefinition,
AST_NODE_TYPES.TSAbstractPropertyDefinition,
select
.or(
select.and(
select.node(AST_NODE_TYPES.TSPropertySignature),
select.not(functionSignature),
),
)
.or(
select.and(
select
.or(select.node(AST_NODE_TYPES.PropertyDefinition))
.or(select.node(AST_NODE_TYPES.TSAbstractPropertyDefinition))
.or(select.node(BabelNodeTypes.ClassProperty))
.or(select.node(BabelNodeTypes.ClassPrivateProperty)),
($) => !($.value && functionExpressions.includes($.value.type)),
),
($) => !($.value && functionExpressions.includes($.value.type)),
),
),
C.chain(
C.property("static", C.prefer),
C.by(decorated, C.prefer),
accessibility(),
C.by(abstracted, C.defer),
accessibility(),
C.property("computed", C.defer),
keyIdentifierName(),
),
Expand All @@ -43,15 +47,16 @@ export const comparator = C.chain<TSESTree.Node>(
// constructor signature for interface
// constructor in class is handled as method
C.capture(
select.or(
select.node(AST_NODE_TYPES.TSConstructSignatureDeclaration),
select.and(
select.node(AST_NODE_TYPES.MethodDefinition),
($) =>
$.key.type === AST_NODE_TYPES.Identifier &&
$.key.name === "constructor",
select
.or(select.node(AST_NODE_TYPES.TSConstructSignatureDeclaration))
.or(
select.and(
select.node(AST_NODE_TYPES.MethodDefinition),
($) =>
$.key.type === AST_NODE_TYPES.Identifier &&
$.key.name === "constructor",
),
),
),
C.by(($) => {
if ($.type !== AST_NODE_TYPES.TSConstructSignatureDeclaration) return 0;
return $.params.length;
Expand All @@ -60,19 +65,28 @@ export const comparator = C.chain<TSESTree.Node>(

// method
C.capture(
select.or(
select.node(AST_NODE_TYPES.TSMethodSignature),
select.node(AST_NODE_TYPES.MethodDefinition),
select.node(AST_NODE_TYPES.TSAbstractMethodDefinition),
select.and(
select.node(AST_NODE_TYPES.PropertyDefinition),
($) => $.value != null && functionExpressions.includes($.value.type),
),
select.and(
select.node(AST_NODE_TYPES.TSPropertySignature),
functionSignature,
select
.or(select.node(AST_NODE_TYPES.TSMethodSignature))
.or(select.node(AST_NODE_TYPES.MethodDefinition))
.or(select.node(AST_NODE_TYPES.TSAbstractMethodDefinition))
.or(select.node(BabelNodeTypes.ClassMethod))
.or(select.node(BabelNodeTypes.ClassPrivateMethod))
.or(
select.and(
select.node(
AST_NODE_TYPES.PropertyDefinition,
BabelNodeTypes.ClassProperty,
BabelNodeTypes.ClassPrivateProperty,
),
($) => $.value != null && functionExpressions.includes($.value.type),
),
)
.or(
select.and(
select.node(AST_NODE_TYPES.TSPropertySignature),
functionSignature,
),
),
),
C.chain(
C.property("static", C.prefer),
C.by(decorated, C.prefer),
Expand Down
23 changes: 13 additions & 10 deletions lib/comparator/key-identifier-name.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
import { AST_NODE_TYPES } from "@typescript-eslint/types";
import { C, Comparator } from "./comparator";
import { select } from "./select";
import { BabelNodeTypes, Node } from "../ast";

export const keyIdentifierName = <
T extends {
key: TSESTree.Node;
key: Node;
},
>(): Comparator<T> =>
C.property(
"key",
C.capture<TSESTree.Node, TSESTree.Identifier>(
select.node(AST_NODE_TYPES.Identifier),
C.property("name", C.string),
),
);
C.by(($) => {
switch ($.key.type) {
case AST_NODE_TYPES.Identifier:
case AST_NODE_TYPES.PrivateIdentifier:
return $.key.name;
case BabelNodeTypes.PrivateName:
if ($.key.id.type === AST_NODE_TYPES.Identifier) return $.key.id.name;
}
return null;
}, C.maybe(C.string));
7 changes: 5 additions & 2 deletions lib/comparator/method-kind.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
import { AST_NODE_TYPES } from "@typescript-eslint/types";
import { C, Comparator } from "./comparator";
import { BabelNodeTypes, Node } from "../ast";

export function methodKind<T extends TSESTree.Node>(): Comparator<T> {
export function methodKind<T extends Node>(): Comparator<T> {
return C.by(($) => {
switch ($.type) {
case AST_NODE_TYPES.TSMethodSignature:
case AST_NODE_TYPES.MethodDefinition:
case AST_NODE_TYPES.TSAbstractMethodDefinition:
case BabelNodeTypes.ClassMethod:
case BabelNodeTypes.TSDeclareMethod:
switch ($.kind) {
case "constructor":
return 0;
Expand Down
Loading

0 comments on commit a9b848f

Please sign in to comment.