Skip to content

Commit

Permalink
feat: add interface and type literal getters & setters (#1473)
Browse files Browse the repository at this point in the history
Co-authored-by: David Sherret <dsherret@gmail.com>
  • Loading branch information
ajvincent and dsherret committed Dec 2, 2023
1 parent e96125e commit 339f685
Show file tree
Hide file tree
Showing 18 changed files with 946 additions and 53 deletions.
92 changes: 91 additions & 1 deletion deno/ts_morph.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ export type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAss
export type CaseOrDefaultClause = CaseClause | DefaultClause;
export type ModuleReference = EntityName | ExternalModuleReference;
export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;
export type TypeElementTypes = PropertySignature | MethodSignature | ConstructSignatureDeclaration | CallSignatureDeclaration | IndexSignatureDeclaration;
export type TypeElementTypes = PropertySignature | MethodSignature | ConstructSignatureDeclaration | CallSignatureDeclaration | IndexSignatureDeclaration | GetAccessorDeclaration | SetAccessorDeclaration;
export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral;
/**
* Local target declarations.
Expand Down Expand Up @@ -2157,6 +2157,94 @@ export interface TypeElementMemberedNode {
getPropertyOrThrow(findFunction: (member: PropertySignature) => boolean): PropertySignature;
/** Gets the interface property signatures. */
getProperties(): PropertySignature[];
/**
* Add get accessor.
* @param structure - Structure representing the get accessor.
*/
addGetAccessor(structure: OptionalKind<GetAccessorDeclarationStructure>): GetAccessorDeclaration;
/**
* Add get accessors.
* @param structures - Structures representing the get accessors.
*/
addGetAccessors(structures: ReadonlyArray<OptionalKind<GetAccessorDeclarationStructure>>): GetAccessorDeclaration[];
/**
* Insert get accessor.
* @param index - Child index to insert at.
* @param structure - Structure representing the get accessor.
*/
insertGetAccessor(index: number, structure: OptionalKind<GetAccessorDeclarationStructure>): GetAccessorDeclaration;
/**
* Insert get accessors.
* @param index - Child index to insert at.
* @param structures - Structures representing the get accessors.
*/
insertGetAccessors(index: number, structures: ReadonlyArray<OptionalKind<GetAccessorDeclarationStructure>>): GetAccessorDeclaration[];
/**
* Gets the first get accessor by name.
* @param name - Name.
*/
getGetAccessor(name: string): GetAccessorDeclaration | undefined;
/**
* Gets the first get accessor by a find function.
* @param findFunction - Function to find the get accessor by.
*/
getGetAccessor(findFunction: (member: GetAccessorDeclaration) => boolean): GetAccessorDeclaration | undefined;
/**
* Gets the first get accessor by name or throws if not found.
* @param name - Name.
*/
getGetAccessorOrThrow(name: string): GetAccessorDeclaration;
/**
* Gets the first get accessor by a find function or throws if not found.
* @param findFunction - Function to find the get accessor by.
*/
getGetAccessorOrThrow(findFunction: (member: GetAccessorDeclaration) => boolean): GetAccessorDeclaration;
/** Gets the interface get accessor declarations. */
getGetAccessors(): GetAccessorDeclaration[];
/**
* Add set accessor.
* @param structure - Structure representing the set accessor.
*/
addSetAccessor(structure: OptionalKind<SetAccessorDeclarationStructure>): SetAccessorDeclaration;
/**
* Add set accessors.
* @param structures - Structures representing the set accessors.
*/
addSetAccessors(structures: ReadonlyArray<OptionalKind<SetAccessorDeclarationStructure>>): SetAccessorDeclaration[];
/**
* Insert set accessor.
* @param index - Child index to insert at.
* @param structure - Structure representing the set accessor.
*/
insertSetAccessor(index: number, structure: OptionalKind<SetAccessorDeclarationStructure>): SetAccessorDeclaration;
/**
* Insert set accessors.
* @param index - Child index to insert at.
* @param structures - Structures representing the set accessors.
*/
insertSetAccessors(index: number, structures: ReadonlyArray<OptionalKind<SetAccessorDeclarationStructure>>): SetAccessorDeclaration[];
/**
* Gets the first set accessor by name.
* @param name - Name.
*/
getSetAccessor(name: string): SetAccessorDeclaration | undefined;
/**
* Gets the first set accessor by a find function.
* @param findFunction - Function to find the set accessor by.
*/
getSetAccessor(findFunction: (member: SetAccessorDeclaration) => boolean): SetAccessorDeclaration | undefined;
/**
* Gets the first set accessor by name or throws if not found.
* @param name - Name.
*/
getSetAccessorOrThrow(name: string): SetAccessorDeclaration;
/**
* Gets the first set accessor by a find function or throws if not found.
* @param findFunction - Function to find the set accessor by.
*/
getSetAccessorOrThrow(findFunction: (member: SetAccessorDeclaration) => boolean): SetAccessorDeclaration;
/** Gets the interface set accessor declarations. */
getSetAccessors(): SetAccessorDeclaration[];
/** Gets all the members. */
getMembers(): TypeElementTypes[];
/** Gets all the members with comment type elements. */
Expand Down Expand Up @@ -10188,9 +10276,11 @@ export interface TypedNodeStructure {
export interface TypeElementMemberedNodeStructure {
callSignatures?: OptionalKind<CallSignatureDeclarationStructure>[];
constructSignatures?: OptionalKind<ConstructSignatureDeclarationStructure>[];
getAccessors?: OptionalKind<GetAccessorDeclarationStructure>[];
indexSignatures?: OptionalKind<IndexSignatureDeclarationStructure>[];
methods?: OptionalKind<MethodSignatureStructure>[];
properties?: OptionalKind<PropertySignatureStructure>[];
setAccessors?: OptionalKind<SetAccessorDeclarationStructure>[];
}

export interface TypeParameteredNodeStructure {
Expand Down
160 changes: 140 additions & 20 deletions deno/ts_morph.js
Original file line number Diff line number Diff line change
Expand Up @@ -6467,6 +6467,41 @@ class NodePrinter extends Printer {
}
}

class GetAndSetAccessorStructurePrinter {
#getAccessorPrinter;
#setAccessorPrinter;
constructor(getAccessorPrinter, setAccessorPrinter) {
this.#getAccessorPrinter = getAccessorPrinter;
this.#setAccessorPrinter = setAccessorPrinter;
}
printGetAndSet(writer, getAccessors, setAccessors, isAmbient) {
getAccessors = [...getAccessors ?? []];
setAccessors = [...setAccessors ?? []];
for (const getAccessor of getAccessors) {
this.#conditionalSeparator(writer, isAmbient);
this.#getAccessorPrinter.printText(writer, getAccessor);
const setAccessorIndex = setAccessors.findIndex(item => item.name === getAccessor.name);
if (setAccessorIndex >= 0) {
this.#conditionalSeparator(writer, isAmbient);
this.#setAccessorPrinter.printText(writer, setAccessors[setAccessorIndex]);
setAccessors.splice(setAccessorIndex, 1);
}
}
for (const setAccessor of setAccessors) {
this.#conditionalSeparator(writer, isAmbient);
this.#setAccessorPrinter.printText(writer, setAccessor);
}
}
#conditionalSeparator(writer, isAmbient) {
if (writer.isAtStartOfFirstLineOfBlock())
return;
if (isAmbient)
writer.newLine();
else
writer.blankLine();
}
}

class ClassDeclarationStructurePrinter extends NodePrinter {
#options;
#multipleWriter = new BlankLineFormattingStructuresPrinter(this);
Expand Down Expand Up @@ -6523,24 +6558,12 @@ class ClassDeclarationStructurePrinter extends NodePrinter {
}
}
#printGetAndSet(writer, structure, isAmbient) {
const getAccessors = [...structure.getAccessors ?? []];
const setAccessors = [...structure.setAccessors ?? []];
if (structure.getAccessors == null && structure.setAccessors == null)
return;
const getAccessorWriter = this.factory.forGetAccessorDeclaration({ isAmbient });
const setAccessorWriter = this.factory.forSetAccessorDeclaration({ isAmbient });
for (const getAccessor of getAccessors) {
this.#conditionalSeparator(writer, isAmbient);
getAccessorWriter.printText(writer, getAccessor);
const setAccessorIndex = setAccessors.findIndex(item => item.name === getAccessor.name);
if (setAccessorIndex >= 0) {
this.#conditionalSeparator(writer, isAmbient);
setAccessorWriter.printText(writer, setAccessors[setAccessorIndex]);
setAccessors.splice(setAccessorIndex, 1);
}
}
for (const setAccessor of setAccessors) {
this.#conditionalSeparator(writer, isAmbient);
setAccessorWriter.printText(writer, setAccessor);
}
const combinedPrinter = new GetAndSetAccessorStructurePrinter(getAccessorWriter, setAccessorWriter);
combinedPrinter.printGetAndSet(writer, structure.getAccessors, structure.setAccessors, isAmbient);
}
#conditionalSeparator(writer, isAmbient) {
if (writer.isAtStartOfFirstLineOfBlock())
Expand Down Expand Up @@ -7552,13 +7575,15 @@ class ConstructorDeclarationStructurePrinter extends NodePrinter {

class GetAccessorDeclarationStructurePrinter extends NodePrinter {
#options;
#blankLineWriter = new BlankLineFormattingStructuresPrinter(this);
#multipleWriter;
constructor(factory, options) {
super(factory);
this.#options = options;
this.#multipleWriter = this.#options.isAmbient ? new NewLineFormattingStructuresPrinter(this) : new BlankLineFormattingStructuresPrinter(this);
}
printTexts(writer, structures) {
this.#blankLineWriter.printText(writer, structures);
if (structures != null)
this.#multipleWriter.printText(writer, structures);
}
printTextInternal(writer, structure) {
this.factory.forJSDoc().printDocs(writer, structure.docs);
Expand Down Expand Up @@ -7667,13 +7692,15 @@ class PropertyDeclarationStructurePrinter extends NodePrinter {

class SetAccessorDeclarationStructurePrinter extends NodePrinter {
#options;
#multipleWriter = new BlankLineFormattingStructuresPrinter(this);
#multipleWriter;
constructor(factory, options) {
super(factory);
this.#options = options;
this.#multipleWriter = this.#options.isAmbient ? new NewLineFormattingStructuresPrinter(this) : new BlankLineFormattingStructuresPrinter(this);
}
printTexts(writer, structures) {
this.#multipleWriter.printText(writer, structures);
if (structures != null)
this.#multipleWriter.printText(writer, structures);
}
printTextInternal(writer, structure) {
this.factory.forJSDoc().printDocs(writer, structure.docs);
Expand Down Expand Up @@ -8167,11 +8194,20 @@ class TypeElementMemberedNodeStructurePrinter extends Printer {
this.#factory.forConstructSignatureDeclaration().printTexts(writer, structure.constructSignatures);
this.#conditionalSeparator(writer, structure.indexSignatures);
this.#factory.forIndexSignatureDeclaration().printTexts(writer, structure.indexSignatures);
this.#printGetAndSet(writer, structure);
this.#conditionalSeparator(writer, structure.properties);
this.#factory.forPropertySignature().printTexts(writer, structure.properties);
this.#conditionalSeparator(writer, structure.methods);
this.#factory.forMethodSignature().printTexts(writer, structure.methods);
}
#printGetAndSet(writer, structure) {
if (structure.getAccessors == null && structure.setAccessors == null)
return;
const getAccessorWriter = this.#factory.forGetAccessorDeclaration({ isAmbient: true });
const setAccessorWriter = this.#factory.forSetAccessorDeclaration({ isAmbient: true });
const combinedPrinter = new GetAndSetAccessorStructurePrinter(getAccessorWriter, setAccessorWriter);
combinedPrinter.printGetAndSet(writer, structure.getAccessors, structure.setAccessors, true);
}
#conditionalSeparator(writer, structures) {
if (!ArrayUtils.isNullOrEmpty(structures) && !writer.isAtStartOfFirstLineOfBlock())
writer.newLine();
Expand Down Expand Up @@ -10360,6 +10396,78 @@ function TypeElementMemberedNode(Base) {
return this.compilerNode.members.filter(m => m.kind === SyntaxKind.PropertySignature)
.map(m => this._getNodeFromCompilerNode(m));
}
addGetAccessor(structure) {
return this.addGetAccessors([structure])[0];
}
addGetAccessors(structures) {
const result = [];
for (const structure of structures) {
const setAccessor = this.getSetAccessor(structure.name);
const index = setAccessor == null ? getEndIndexFromArray(this.getMembersWithComments()) : setAccessor.getChildIndex();
result.push(this.insertGetAccessor(index, structure));
}
return result;
}
insertGetAccessor(index, structure) {
return this.insertGetAccessors(index, [structure])[0];
}
insertGetAccessors(index, structures) {
return insertChildren$1({
thisNode: this,
index,
structures,
expectedKind: SyntaxKind.GetAccessor,
createStructurePrinter: () => this._context.structurePrinterFactory.forGetAccessorDeclaration({
isAmbient: true,
}),
});
}
getGetAccessor(nameOrFindFunction) {
return getNodeByNameOrFindFunction(this.getGetAccessors(), nameOrFindFunction);
}
getGetAccessorOrThrow(nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getGetAccessor(nameOrFindFunction), () => getNotFoundErrorMessageForNameOrFindFunction("interface get accessor", nameOrFindFunction));
}
getGetAccessors() {
return this.compilerNode.members.filter(m => m.kind === SyntaxKind.GetAccessor)
.map(m => this._getNodeFromCompilerNode(m));
}
addSetAccessor(structure) {
return this.addSetAccessors([structure])[0];
}
addSetAccessors(structures) {
const result = [];
for (const structure of structures) {
const getAccessor = this.getGetAccessor(structure.name);
const index = getAccessor == null ? getEndIndexFromArray(this.getMembersWithComments()) : getAccessor.getChildIndex() + 1;
result.push(this.insertSetAccessor(index, structure));
}
return result;
}
insertSetAccessor(index, structure) {
return this.insertSetAccessors(index, [structure])[0];
}
insertSetAccessors(index, structures) {
return insertChildren$1({
thisNode: this,
index,
structures,
expectedKind: SyntaxKind.SetAccessor,
createStructurePrinter: () => this._context.structurePrinterFactory.forSetAccessorDeclaration({
isAmbient: true,
}),
});
}
getSetAccessor(nameOrFindFunction) {
return getNodeByNameOrFindFunction(this.getSetAccessors(), nameOrFindFunction);
}
getSetAccessorOrThrow(nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getSetAccessor(nameOrFindFunction), () => getNotFoundErrorMessageForNameOrFindFunction("interface set accessor", nameOrFindFunction));
}
getSetAccessors() {
return this.compilerNode.members.filter(m => m.kind === SyntaxKind.SetAccessor)
.map(m => this._getNodeFromCompilerNode(m));
}
getMembers() {
return this.compilerNode.members.map(m => this._getNodeFromCompilerNode(m));
}
Expand All @@ -10386,6 +10494,14 @@ function TypeElementMemberedNode(Base) {
this.getProperties().forEach(c => c.remove());
this.addProperties(structure.properties);
}
if (structure.getAccessors != null) {
this.getGetAccessors().forEach(c => c.remove());
this.addGetAccessors(structure.getAccessors);
}
if (structure.setAccessors != null) {
this.getSetAccessors().forEach(c => c.remove());
this.addSetAccessors(structure.setAccessors);
}
if (structure.methods != null) {
this.getMethods().forEach(c => c.remove());
this.addMethods(structure.methods);
Expand All @@ -10396,9 +10512,11 @@ function TypeElementMemberedNode(Base) {
return callBaseGetStructure(Base.prototype, this, {
callSignatures: this.getCallSignatures().map(node => node.getStructure()),
constructSignatures: this.getConstructSignatures().map(node => node.getStructure()),
getAccessors: this.getGetAccessors().map(node => node.getStructure()),
indexSignatures: this.getIndexSignatures().map(node => node.getStructure()),
methods: this.getMethods().map(node => node.getStructure()),
properties: this.getProperties().map(node => node.getStructure()),
setAccessors: this.getSetAccessors().map(node => node.getStructure()),
});
}
};
Expand Down Expand Up @@ -13947,6 +14065,8 @@ class ClassElement extends Node {
removeClassMember(this);
else if (Node.isObjectLiteralExpression(parent))
removeCommaSeparatedChild(this);
else if (Node.isInterfaceDeclaration(parent))
removeInterfaceMember(this);
else
errors.throwNotImplementedForSyntaxKindError(parent.getKind());
}
Expand Down

0 comments on commit 339f685

Please sign in to comment.