// noinspection JSUnusedGlobalSymbols
/*
* Copyright 2025 the original author or authors.
*
* Licensed under the Moderne Source Available License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://docs.moderne.io/licensing/moderne-source-available-license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {emptyMarkers, Markers} from "../markers";
import {SourceFile, Tree} from "../tree";
import {Type} from "./type";
export interface J extends Tree {
readonly prefix: J.Space;
}
export namespace J {
export function isMethodCall(e?: Expression): e is MethodCall {
return e?.kind === J.Kind.NewClass ||
e?.kind === J.Kind.MethodInvocation ||
e?.kind === J.Kind.MemberReference;
}
export function hasType(tree: T): tree is T & { type: Type } {
return tree && 'type' in tree && tree.type != null;
}
}
export interface Expression extends J {
readonly type?: Type;
}
export interface MethodCall extends Expression {
readonly methodType?: Type.Method;
}
export interface TypedTree extends J {
}
export interface NameTree extends TypedTree {
}
export interface TypeTree extends NameTree {
}
export interface VariableDeclarator extends J {
}
export interface JavaSourceFile extends J, SourceFile {
readonly packageDeclaration: J.RightPadded;
readonly imports: J.RightPadded[];
readonly classes: J.ClassDeclaration[];
}
export interface Statement extends J {
}
export interface NameTree extends J {
}
export namespace J {
export const Kind = {
AnnotatedType: "org.openrewrite.java.tree.J$AnnotatedType",
Annotation: "org.openrewrite.java.tree.J$Annotation",
ArrayAccess: "org.openrewrite.java.tree.J$ArrayAccess",
ArrayDimension: "org.openrewrite.java.tree.J$ArrayDimension",
ArrayType: "org.openrewrite.java.tree.J$ArrayType",
Assert: "org.openrewrite.java.tree.J$Assert",
Assignment: "org.openrewrite.java.tree.J$Assignment",
AssignmentOperation: "org.openrewrite.java.tree.J$AssignmentOperation",
Binary: "org.openrewrite.java.tree.J$Binary",
Block: "org.openrewrite.java.tree.J$Block",
Break: "org.openrewrite.java.tree.J$Break",
Case: "org.openrewrite.java.tree.J$Case",
ClassDeclaration: "org.openrewrite.java.tree.J$ClassDeclaration",
ClassDeclarationKind: "org.openrewrite.java.tree.J$ClassDeclaration$Kind",
ControlParentheses: "org.openrewrite.java.tree.J$ControlParentheses",
CompilationUnit: "org.openrewrite.java.tree.J$CompilationUnit",
Continue: "org.openrewrite.java.tree.J$Continue",
DeconstructionPattern: "org.openrewrite.java.tree.J$DeconstructionPattern",
DoWhileLoop: "org.openrewrite.java.tree.J$DoWhileLoop",
Empty: "org.openrewrite.java.tree.J$Empty",
EnumValueSet: "org.openrewrite.java.tree.J$EnumValueSet",
EnumValue: "org.openrewrite.java.tree.J$EnumValue",
Erroneous: "org.openrewrite.java.tree.J$Erroneous",
FieldAccess: "org.openrewrite.java.tree.J$FieldAccess",
ForEachLoop: "org.openrewrite.java.tree.J$ForEachLoop",
ForEachLoopControl: "org.openrewrite.java.tree.J$ForEachLoop$Control",
ForLoop: "org.openrewrite.java.tree.J$ForLoop",
ForLoopControl: "org.openrewrite.java.tree.J$ForLoop$Control",
Identifier: "org.openrewrite.java.tree.J$Identifier",
If: "org.openrewrite.java.tree.J$If",
IfElse: "org.openrewrite.java.tree.J$If$Else",
Import: "org.openrewrite.java.tree.J$Import",
InstanceOf: "org.openrewrite.java.tree.J$InstanceOf",
IntersectionType: "org.openrewrite.java.tree.J$IntersectionType",
Label: "org.openrewrite.java.tree.J$Label",
Lambda: "org.openrewrite.java.tree.J$Lambda",
LambdaParameters: "org.openrewrite.java.tree.J$Lambda$Parameters",
Literal: "org.openrewrite.java.tree.J$Literal",
MemberReference: "org.openrewrite.java.tree.J$MemberReference",
MethodDeclaration: "org.openrewrite.java.tree.J$MethodDeclaration",
MethodInvocation: "org.openrewrite.java.tree.J$MethodInvocation",
Modifier: "org.openrewrite.java.tree.J$Modifier",
MultiCatch: "org.openrewrite.java.tree.J$MultiCatch",
NamedVariable: "org.openrewrite.java.tree.J$VariableDeclarations$NamedVariable",
NewArray: "org.openrewrite.java.tree.J$NewArray",
NewClass: "org.openrewrite.java.tree.J$NewClass",
NullableType: "org.openrewrite.java.tree.J$NullableType",
Package: "org.openrewrite.java.tree.J$Package",
ParameterizedType: "org.openrewrite.java.tree.J$ParameterizedType",
Parentheses: "org.openrewrite.java.tree.J$Parentheses",
ParenthesizedTypeTree: "org.openrewrite.java.tree.J$ParenthesizedTypeTree",
Primitive: "org.openrewrite.java.tree.J$Primitive",
Return: "org.openrewrite.java.tree.J$Return",
Switch: "org.openrewrite.java.tree.J$Switch",
SwitchExpression: "org.openrewrite.java.tree.J$SwitchExpression",
Synchronized: "org.openrewrite.java.tree.J$Synchronized",
Ternary: "org.openrewrite.java.tree.J$Ternary",
TextComment: "org.openrewrite.java.tree.TextComment",
Throw: "org.openrewrite.java.tree.J$Throw",
Try: "org.openrewrite.java.tree.J$Try",
TryResource: "org.openrewrite.java.tree.J$Try$Resource",
TryCatch: "org.openrewrite.java.tree.J$Try$Catch",
TypeCast: "org.openrewrite.java.tree.J$TypeCast",
TypeParameter: "org.openrewrite.java.tree.J$TypeParameter",
TypeParameters: "org.openrewrite.java.tree.J$TypeParameters",
Unary: "org.openrewrite.java.tree.J$Unary",
Unknown: "org.openrewrite.java.tree.J$Unknown",
UnknownSource: "org.openrewrite.java.tree.J$Unknown$Source",
VariableDeclarations: "org.openrewrite.java.tree.J$VariableDeclarations",
WhileLoop: "org.openrewrite.java.tree.J$WhileLoop",
Wildcard: "org.openrewrite.java.tree.J$Wildcard",
Yield: "org.openrewrite.java.tree.J$Yield",
Container: "org.openrewrite.java.tree.JContainer",
LeftPadded: "org.openrewrite.java.tree.JLeftPadded",
RightPadded: "org.openrewrite.java.tree.JRightPadded",
Space: "org.openrewrite.java.tree.Space",
} as const;
export interface AnnotatedType extends J, TypeTree, Expression {
readonly kind: typeof Kind.AnnotatedType;
readonly annotations: Annotation[];
readonly typeExpression: TypeTree;
}
export interface Annotation extends J, Expression {
readonly kind: typeof Kind.Annotation;
readonly annotationType: NameTree;
readonly arguments?: Container;
}
export interface ArrayAccess extends J, TypedTree, Expression {
readonly kind: typeof Kind.ArrayAccess;
readonly indexed: Expression;
readonly dimension: ArrayDimension;
readonly type?: Type
}
export interface ArrayDimension extends J {
readonly kind: typeof Kind.ArrayDimension;
readonly index: RightPadded;
}
export interface ArrayType extends J, TypeTree, Expression {
readonly kind: typeof Kind.ArrayType;
readonly elementType: TypeTree;
readonly annotations?: Annotation[];
readonly dimension: LeftPadded;
readonly type?: Type;
}
export interface Assert extends J, Statement {
readonly kind: typeof Kind.Assert;
readonly condition: Expression;
readonly detail?: LeftPadded;
}
export interface Assignment extends J, Statement, Expression, TypedTree {
readonly kind: typeof Kind.Assignment;
readonly variable: Expression;
readonly assignment: LeftPadded;
readonly type?: Type;
}
export interface AssignmentOperation extends J, Statement, Expression, TypedTree {
readonly kind: typeof Kind.AssignmentOperation;
readonly variable: Expression;
readonly operator: LeftPadded;
readonly assignment: Expression;
readonly type?: Type;
}
export namespace AssignmentOperation {
export const enum Type {
Addition = "Addition",
BitAnd = "BitAnd",
BitOr = "BitOr",
BitXor = "BitXor",
Division = "Division",
Exponentiation = "Exponentiation", // Raises the left operand to the power of the right operand. Used in Python
FloorDivision = "FloorDivision", // Division rounding down to the nearest integer. Used in Python
LeftShift = "LeftShift",
MatrixMultiplication = "MatrixMultiplication", // Matrix multiplication. Used in Python
Modulo = "Modulo",
Multiplication = "Multiplication",
RightShift = "RightShift",
Subtraction = "Subtraction",
UnsignedRightShift = "UnsignedRightShift"
}
}
export interface Binary extends J, Expression, TypedTree {
readonly kind: typeof Kind.Binary;
readonly left: Expression;
readonly operator: LeftPadded;
readonly right: Expression;
readonly type?: Type;
}
export namespace Binary {
export const enum Type {
Addition = "Addition",
Subtraction = "Subtraction",
Multiplication = "Multiplication",
Division = "Division",
Modulo = "Modulo",
LessThan = "LessThan",
GreaterThan = "GreaterThan",
LessThanOrEqual = "LessThanOrEqual",
GreaterThanOrEqual = "GreaterThanOrEqual",
Equal = "Equal",
NotEqual = "NotEqual",
BitAnd = "BitAnd",
BitOr = "BitOr",
BitXor = "BitXor",
LeftShift = "LeftShift",
RightShift = "RightShift",
UnsignedRightShift = "UnsignedRightShift",
Or = "Or",
And = "And"
}
}
export interface Block extends J {
readonly kind: typeof Kind.Block;
readonly static: RightPadded;
readonly statements: RightPadded[];
readonly end: J.Space;
}
export interface Break extends J, Statement {
readonly kind: typeof Kind.Break;
readonly label?: Identifier;
}
export interface Case extends J, Statement {
readonly kind: typeof Kind.Case;
readonly type: Case.Type;
readonly caseLabels: Container;
readonly statements: Container;
readonly body?: RightPadded;
readonly guard?: Expression;
}
export namespace Case {
export const enum Type {
Statement = "Statement",
Rule = "Rule"
}
}
export interface ClassDeclaration extends J, Statement, TypedTree {
readonly kind: typeof Kind.ClassDeclaration;
readonly leadingAnnotations: Annotation[];
readonly modifiers: Modifier[];
readonly classKind: ClassDeclaration.Kind;
readonly name: Identifier;
readonly typeParameters?: Container;
readonly primaryConstructor?: Container;
readonly extends?: LeftPadded;
readonly implements?: Container;
readonly permitting?: Container;
readonly body: Block;
readonly type?: Type.FullyQualified;
}
export namespace ClassDeclaration {
export interface Kind extends J {
readonly kind: typeof J.Kind.ClassDeclarationKind;
readonly annotations: Annotation[];
readonly type: Kind.Type;
}
export namespace Kind {
export const enum Type {
Class = "Class",
Interface = "Interface",
Enum = "Enum",
Annotation = "Annotation",
Record = "Record",
Value = "Value"
}
}
}
export interface CompilationUnit extends JavaSourceFile, J {
readonly kind: typeof Kind.CompilationUnit;
readonly eof: Space;
}
export interface Continue extends J, Statement {
readonly kind: typeof Kind.Continue;
readonly label?: Identifier;
}
export interface DoWhileLoop extends J, Statement {
readonly kind: typeof Kind.DoWhileLoop;
readonly body: RightPadded;
readonly whileCondition: LeftPadded>;
}
export interface Empty extends J, Statement, TypeTree, Expression {
readonly kind: typeof Kind.Empty;
}
export interface EnumValue extends J {
readonly kind: typeof Kind.EnumValue;
readonly annotations: Annotation[];
readonly name: Identifier;
readonly initializer?: NewClass;
}
export interface EnumValueSet extends J, Statement {
readonly kind: typeof Kind.EnumValueSet;
readonly enums: RightPadded[];
readonly terminatedWithSemicolon: boolean;
}
export interface FieldAccess extends Statement, Expression, TypeTree {
readonly kind: typeof Kind.FieldAccess;
readonly target: Expression;
readonly name: LeftPadded;
readonly type?: Type;
}
export interface ForEachLoop extends J, Statement {
readonly kind: typeof Kind.ForEachLoop;
readonly control: ForEachLoop.Control;
readonly body: RightPadded;
}
export namespace ForEachLoop {
export interface Control extends J {
readonly kind: typeof Kind.ForEachLoopControl;
readonly variable: RightPadded;
readonly iterable: RightPadded;
}
}
export interface ForLoop extends J, Statement {
readonly kind: typeof Kind.ForLoop;
readonly control: ForLoop.Control;
readonly body: RightPadded;
}
export namespace ForLoop {
export interface Control extends J {
readonly kind: typeof Kind.ForLoopControl;
readonly init: RightPadded[];
readonly condition?: RightPadded;
readonly update: RightPadded[];
}
}
export interface ParenthesizedTypeTree extends J, TypeTree, Expression {
readonly kind: typeof Kind.ParenthesizedTypeTree;
readonly annotations: Annotation[];
readonly parenthesizedType: Parentheses;
}
export interface Identifier extends J, TypeTree, Expression, VariableDeclarator {
readonly kind: typeof Kind.Identifier;
readonly annotations: Annotation[];
readonly simpleName: string;
readonly type?: Type;
readonly fieldType?: Type.Variable;
}
export interface If extends J, Statement {
readonly kind: typeof Kind.If;
readonly ifCondition: ControlParentheses;
readonly thenPart: RightPadded;
readonly elsePart?: If.Else;
}
export namespace If {
export interface Else extends J {
readonly kind: typeof Kind.IfElse;
readonly body: RightPadded;
}
}
export interface Import extends J {
readonly kind: typeof Kind.Import;
readonly static: LeftPadded;
readonly qualid: FieldAccess;
readonly alias?: LeftPadded;
}
export interface InstanceOf extends J, Expression, TypedTree {
readonly kind: typeof Kind.InstanceOf;
readonly expression: RightPadded;
readonly class: J;
readonly pattern?: J;
readonly type?: Type;
readonly modifier?: Modifier;
}
export interface DeconstructionPattern extends J, TypedTree {
readonly kind: typeof Kind.DeconstructionPattern;
readonly deconstructor: Expression;
readonly nested: Container;
readonly type?: Type;
}
export interface IntersectionType extends J, TypeTree, Expression {
readonly kind: typeof Kind.IntersectionType;
readonly bounds: Container;
readonly type?: Type;
}
export interface Label extends J, Statement {
readonly kind: typeof Kind.Label;
readonly label: RightPadded;
readonly statement: Statement;
}
export interface Lambda extends J, Statement, TypedTree, Expression {
readonly kind: typeof Kind.Lambda;
readonly parameters: Lambda.Parameters;
readonly arrow: Space;
readonly body: Statement | Expression;
readonly type?: Type;
}
export namespace Lambda {
export interface Parameters extends J {
readonly kind: typeof Kind.LambdaParameters;
readonly parenthesized: boolean;
readonly parameters: RightPadded[];
}
}
export interface Literal extends J, TypedTree, Expression, VariableDeclarator {
readonly kind: typeof Kind.Literal;
readonly value?: string | number | bigint | boolean | null | undefined;
readonly valueSource?: string;
readonly unicodeEscapes?: LiteralUnicodeEscape[];
readonly type?: Type.Primitive;
}
export interface LiteralUnicodeEscape {
readonly valueSourceIndex: number;
readonly codePoint: string;
}
export interface MemberReference extends J, MethodCall {
readonly kind: typeof Kind.MemberReference;
readonly containing: RightPadded;
readonly typeParameters?: Container;
readonly reference: LeftPadded;
readonly type?: Type;
readonly variableType?: Type.Variable;
}
export interface MethodDeclaration extends J, TypedTree {
readonly kind: typeof Kind.MethodDeclaration;
readonly leadingAnnotations: Annotation[];
readonly modifiers: Modifier[];
readonly typeParameters?: TypeParameters;
readonly returnTypeExpression?: TypeTree;
readonly nameAnnotations: Annotation[];
readonly name: Identifier;
readonly parameters: Container;
readonly dimensionsAfterName: LeftPadded[];
readonly throws?: Container;
readonly body?: Block;
readonly defaultValue?: LeftPadded;
readonly methodType?: Type.Method;
}
export interface MethodInvocation extends J, TypedTree, MethodCall {
readonly kind: typeof Kind.MethodInvocation;
readonly select?: RightPadded;
readonly typeParameters?: Container;
readonly name: Identifier;
readonly arguments: Container;
}
export interface Modifier extends J {
readonly kind: typeof Kind.Modifier;
readonly keyword?: string;
readonly type: ModifierType;
readonly annotations: Annotation[];
}
export const enum ModifierType {
Default = "Default",
Public = "Public",
Protected = "Protected",
Private = "Private",
Abstract = "Abstract",
Static = "Static",
Final = "Final",
Sealed = "Sealed",
NonSealed = "NonSealed",
Transient = "Transient",
Volatile = "Volatile",
Synchronized = "Synchronized",
Native = "Native",
Strictfp = "Strictfp",
Async = "Async",
Reified = "Reified",
Inline = "Inline",
/**
* For modifiers not seen in Java this is used in conjunction with "keyword"
*/
LanguageExtension = "LanguageExtension"
}
export interface MultiCatch extends J, TypeTree {
readonly kind: typeof Kind.MultiCatch;
readonly alternatives: RightPadded[];
}
export interface NewArray extends J, TypedTree, Expression {
readonly kind: typeof Kind.NewArray;
readonly typeExpression?: TypeTree;
readonly dimensions: ArrayDimension[];
readonly initializer?: Container;
readonly type?: Type;
}
export interface NewClass extends J, TypedTree, MethodCall {
readonly kind: typeof Kind.NewClass;
readonly enclosing?: RightPadded;
readonly new: Space;
readonly class?: TypeTree;
readonly arguments: Container;
readonly body?: Block;
readonly constructorType?: Type.Method;
}
export interface NullableType extends J, TypeTree, Expression {
readonly kind: typeof Kind.NullableType;
readonly annotations: Annotation[];
readonly typeTree: RightPadded;
}
export interface Package extends J {
readonly kind: typeof Kind.Package;
readonly expression: Expression;
readonly annotations?: Annotation[];
}
export interface ParameterizedType extends J, TypeTree {
readonly kind: typeof Kind.ParameterizedType;
readonly class: NameTree;
readonly typeParameters?: Container;
readonly type?: Type;
}
export interface Parentheses extends J, Expression {
readonly kind: typeof Kind.Parentheses;
readonly tree: RightPadded;
}
export interface ControlParentheses extends J, Expression {
readonly kind: typeof Kind.ControlParentheses;
readonly tree: RightPadded;
}
export interface Primitive extends J, TypeTree, Expression {
readonly kind: typeof Kind.Primitive;
type: Type.Primitive;
}
export interface Return extends J, Statement {
readonly kind: typeof Kind.Return;
readonly expression?: Expression;
}
export interface Switch extends J, Statement {
readonly kind: typeof Kind.Switch;
readonly selector: ControlParentheses;
readonly cases: Block;
}
export interface SwitchExpression extends J, TypedTree, Expression {
readonly kind: typeof Kind.SwitchExpression;
readonly selector: ControlParentheses;
readonly cases: Block;
readonly type?: Type;
}
export interface Synchronized extends J, Statement {
readonly kind: typeof Kind.Synchronized;
readonly lock: ControlParentheses;
readonly body: Block;
}
export interface Ternary extends J, Statement, Expression, TypedTree {
readonly kind: typeof Kind.Ternary;
readonly condition: Expression;
readonly truePart: LeftPadded;
readonly falsePart: LeftPadded;
readonly type?: Type;
}
export interface Throw extends J, Statement {
readonly kind: typeof Kind.Throw;
readonly exception: Expression;
}
export interface Try extends J, Statement {
readonly kind: typeof Kind.Try;
readonly resources?: Container;
readonly body: Block;
readonly catches: Try.Catch[];
readonly finally?: LeftPadded;
}
export namespace Try {
export interface Resource extends J {
readonly kind: typeof Kind.TryResource;
readonly variableDeclarations: TypedTree;
readonly terminatedWithSemicolon: boolean;
}
export interface Catch extends J {
readonly kind: typeof Kind.TryCatch;
readonly parameter: ControlParentheses;
readonly body: Block;
}
}
export interface TypeCast extends J, TypedTree, Expression {
readonly kind: typeof Kind.TypeCast;
readonly class: ControlParentheses;
readonly expression: Expression;
}
export interface TypeParameter extends J {
readonly kind: typeof Kind.TypeParameter;
readonly annotations: Annotation[];
readonly modifiers: Modifier[];
readonly name: Expression;
readonly bounds?: Container;
}
export interface TypeParameters extends J {
readonly kind: typeof Kind.TypeParameters;
readonly annotations: Annotation[];
readonly typeParameters: RightPadded[];
}
export interface Unary extends J, Statement, Expression, TypedTree {
readonly kind: typeof Kind.Unary;
readonly operator: LeftPadded;
readonly expression: Expression;
readonly type?: Type;
}
export namespace Unary {
export const enum Type {
PreIncrement = "PreIncrement",
PreDecrement = "PreDecrement",
PostIncrement = "PostIncrement",
PostDecrement = "PostDecrement",
Positive = "Positive",
Negative = "Negative",
Complement = "Complement",
Not = "Not"
}
}
export interface VariableDeclarations extends J, TypedTree {
readonly kind: typeof Kind.VariableDeclarations;
readonly leadingAnnotations: Annotation[];
readonly modifiers: Modifier[];
readonly typeExpression?: TypeTree;
readonly varargs?: Space;
readonly variables: RightPadded[];
}
export namespace VariableDeclarations {
export interface NamedVariable extends J {
readonly kind: typeof Kind.NamedVariable;
readonly name: VariableDeclarator;
readonly dimensionsAfterName: LeftPadded[];
readonly initializer?: LeftPadded;
readonly variableType?: Type.Variable;
}
}
export interface WhileLoop extends J, Statement {
readonly kind: typeof Kind.WhileLoop;
readonly condition: ControlParentheses;
readonly body: RightPadded;
}
export interface Wildcard extends J, TypeTree, Expression {
readonly kind: typeof Kind.Wildcard;
readonly bound?: LeftPadded;
readonly boundedType?: NameTree;
}
export namespace Wildcard {
export const enum Bound {
Extends = "Extends",
Super = "Super"
}
}
export interface Yield extends J, Statement {
readonly kind: typeof Kind.Yield;
readonly implicit: boolean;
readonly value: Expression;
}
export interface Unknown extends J, Statement, Expression, TypeTree {
readonly kind: typeof Kind.Unknown;
readonly source: UnknownSource;
}
export interface UnknownSource extends J {
readonly kind: typeof Kind.UnknownSource;
readonly text: string;
}
export interface Erroneous extends J, Expression, Statement {
readonly kind: typeof Kind.Erroneous;
readonly text: string;
}
export interface LeftPadded {
readonly kind: typeof Kind.LeftPadded;
readonly before: Space;
readonly element: T;
readonly markers: Markers;
}
export interface RightPadded {
readonly kind: typeof Kind.RightPadded;
readonly element: T;
readonly after: Space;
readonly markers: Markers;
}
export interface Container {
readonly kind: typeof Kind.Container;
readonly before: Space;
readonly elements: RightPadded[];
readonly markers: Markers;
}
export interface Space {
readonly kind: typeof J.Kind.Space;
readonly comments: Comment[];
readonly whitespace: string;
}
}
export function isSpace(tree: any): tree is J.Space {
return tree &&
typeof tree === 'object' &&
tree.kind === J.Kind.Space;
}
/**
* Builds a comment-free Space. Assigning one over an existing prefix silently drops the comments
* that prefix carried; spread the prefix to keep them — `{...prefix, whitespace: "\n\n"}`.
*/
export function space(whitespace: string): J.Space {
return {
kind: J.Kind.Space,
comments: [],
whitespace: whitespace,
};
}
export const emptySpace: J.Space = {
kind: J.Kind.Space,
comments: [],
whitespace: "",
};
export const singleSpace: J.Space = {
kind: J.Kind.Space,
comments: [],
whitespace: " ",
};
export function emptyContainer(): J.Container {
return {
kind: J.Kind.Container,
before: emptySpace,
elements: [],
markers: emptyMarkers,
};
}
export interface Comment {
readonly kind: string
readonly suffix: string;
readonly markers: Markers;
}
export interface TextComment extends Comment {
readonly kind: typeof J.Kind.TextComment
readonly multiline: boolean;
readonly text: string;
readonly suffix: string;
readonly markers: Markers;
}
export interface DocComment extends Comment {
// TODO implement me!
}
export const isBinary = (n: any): n is J.Binary => n.kind === J.Kind.Binary;
export const isBlock = (n: any): n is J.Block => n.kind === J.Kind.Block;
export const isClassDeclaration = (n: any): n is J.ClassDeclaration => n.kind === J.Kind.ClassDeclaration;
export const isFieldAccess = (n: any): n is J.FieldAccess => n.kind === J.Kind.FieldAccess;
export const isIdentifier = (tree: any): tree is J.Identifier => tree["kind"] === J.Kind.Identifier;
export const isIf = (tree: any): tree is J.If => tree["kind"] === J.Kind.If;
export const isImport = (tree: any): tree is J.Import => tree["kind"] === J.Kind.Import;
export const isLambda = (tree: any): tree is J.Lambda => tree["kind"] === J.Kind.Lambda;
export const isLiteral = (tree: any): tree is J.Literal => tree["kind"] === J.Kind.Literal;
export const isMethodDeclaration = (n: any): n is J.MethodDeclaration => n.kind === J.Kind.MethodDeclaration;
export const isMethodInvocation = (n: any): n is J.MethodInvocation => n.kind === J.Kind.MethodInvocation;
export const isNamedVariable = (n: any): n is J.VariableDeclarations.NamedVariable => n.kind === J.Kind.NamedVariable;
export const isNewClass = (n: any): n is J.NewClass => n.kind === J.Kind.NewClass;
export const isReturn = (n: any): n is J.Return => n.kind === J.Kind.Return;
export const isVariableDeclarations = (n: any): n is J.VariableDeclarations => n.kind === J.Kind.VariableDeclarations;
export function rightPadded(t: T, trailing: J.Space, markers?: Markers): J.RightPadded {
return {
kind: J.Kind.RightPadded,
element: t,
after: trailing,
markers: markers ?? emptyMarkers
};
}
export namespace TypedTree {
const typeGetters = new Map Type | undefined>();
export function getType(typeTree?: TypedTree): Type | undefined {
if (!typeTree) {
return undefined;
}
const customFn = typeGetters.get(typeTree.kind as any);
if (customFn) {
return customFn(typeTree as any) as any;
}
if ("typeExpression" in typeTree && (typeTree as any).typeExpression) {
return getType((typeTree as any).typeExpression);
}
return (typeTree as any).type;
}
export function registerTypeGetter(kind: T["kind"], fn: (tree: T) => Type | undefined): void {
typeGetters.set(kind, fn as any);
}
registerTypeGetter(J.Kind.MethodDeclaration, (tree: J.MethodDeclaration) => tree.methodType?.returnType);
registerTypeGetter(J.Kind.MethodInvocation, (tree: J.MethodInvocation) => tree.methodType?.returnType);
registerTypeGetter(J.Kind.Parentheses, (tree: J.Parentheses) => getType(tree.tree.element));
registerTypeGetter(J.Kind.NewClass, (tree: J.NewClass) => tree.constructorType?.returnType);
// TODO ControlParentheses here isn't a TypedTree so why does this compile?
registerTypeGetter(J.Kind.TypeCast, (tree: J.TypeCast) => getType(tree.class));
registerTypeGetter(J.Kind.Empty, () => Type.unknownType);
registerTypeGetter(J.Kind.MultiCatch, (tree: J.MultiCatch) => {
const bounds = tree.alternatives.map(a => getType(a.element));
return {kind: Type.Kind.Union, bounds: bounds};
});
registerTypeGetter(J.Kind.NullableType, (tree: J.NullableType) => getType(tree.typeTree.element));
registerTypeGetter(J.Kind.Wildcard, () => Type.unknownType);
registerTypeGetter(J.Kind.Unknown, () => Type.unknownType);
}