diff --git a/examples/hello-world-abi/contract.algo.ts b/examples/hello-world-abi/contract.algo.ts index f27adf07..cd754ba0 100644 --- a/examples/hello-world-abi/contract.algo.ts +++ b/examples/hello-world-abi/contract.algo.ts @@ -1,18 +1,31 @@ -import { arc4, log } from '@algorandfoundation/algorand-typescript' +import { arc4 } from '@algorandfoundation/algorand-typescript' +/** + * An abstract base class for a simple example contract + */ abstract class Intermediate extends arc4.Contract { + /** + * sayBananas method + * @returns The string "Bananas" + */ @arc4.abimethod({ allowActions: ['NoOp'], readonly: true }) public sayBananas(): string { - const result = `Bananas` - log(result) - return result + return `Bananas` } } +/** + * A simple hello world example contract + */ export default class HelloWorldContract extends Intermediate { + /** + * sayHello method + * @param firstName The first name of the person to greet + * @param lastName THe last name of the person to greet + * @returns The string "Hello {firstName} {lastName"} + */ public sayHello(firstName: string, lastName: string): string { const result = `Hello ${firstName} ${lastName}` - log(result) return result } } diff --git a/package.json b/package.json index 6bcc77e3..6f90c571 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dev:examples": "tsx src/cli.ts build examples --output-awst --output-awst-json", "dev:approvals": "rimraf tests/approvals/out && tsx src/cli.ts build tests/approvals --dry-run", "dev:expected-output": "tsx src/cli.ts build tests/expected-output --dry-run", - "dev:testing": "tsx src/cli.ts build tests/approvals/arc4-types.algo.ts --output-awst --output-awst-json --output-ssa-ir --log-level=info --log-level debug --out-dir out/[name]", + "dev:testing": "tsx src/cli.ts build tests/approvals/jsdoc.algo.ts --output-awst --output-awst-json --output-ssa-ir --log-level=info --log-level info --out-dir out/[name]", "audit": "better-npm-audit audit", "format": "prettier --write .", "lint": "eslint \"src/**/*.ts\"", diff --git a/src/awst/wtypes.ts b/src/awst/wtypes.ts index 0c7bb00f..c8b4484f 100644 --- a/src/awst/wtypes.ts +++ b/src/awst/wtypes.ts @@ -251,15 +251,18 @@ export namespace wtypes { fields: Record sourceLocation: SourceLocation | null frozen: boolean + desc: string | null constructor({ fields, sourceLocation, name, + desc, frozen, }: { frozen: boolean name: string + desc: string | null fields: Record sourceLocation?: SourceLocation }) { @@ -273,6 +276,7 @@ export namespace wtypes { this.sourceLocation = sourceLocation ?? null this.fields = fields this.frozen = frozen + this.desc = desc } } export class ARC4Tuple extends ARC4Type { diff --git a/src/awst_build/arc4-util.ts b/src/awst_build/arc4-util.ts index 090db561..1a720605 100644 --- a/src/awst_build/arc4-util.ts +++ b/src/awst_build/arc4-util.ts @@ -61,6 +61,7 @@ export function ptypeToArc4EncodedType(ptype: PType, sourceLocation: SourceLocat return new ARC4StructType({ name: ptype.name, module: ptype.module, + description: ptype.description, fields: Object.fromEntries(ptype.orderedProperties().map(([p, pt]) => [p, ptypeToArc4EncodedType(pt, sourceLocation)])), }) diff --git a/src/awst_build/ast-visitors/base-visitor.ts b/src/awst_build/ast-visitors/base-visitor.ts index 9e3237da..b6bf064b 100644 --- a/src/awst_build/ast-visitors/base-visitor.ts +++ b/src/awst_build/ast-visitors/base-visitor.ts @@ -1,6 +1,6 @@ import ts from 'typescript' import { nodeFactory } from '../../awst/node-factory' -import type { Expression, LValue, Statement } from '../../awst/nodes' +import type { Expression, LValue, MethodDocumentation, Statement } from '../../awst/nodes' import type { SourceLocation } from '../../awst/source-location' import { CodeError, NotSupported, TodoError } from '../../errors' import { logger } from '../../logger' @@ -554,6 +554,7 @@ export abstract class BaseVisitor implements Visitor { return new ObjectPType({ name: targetType.name, module: targetType.module, + description: targetType.description, properties: Object.fromEntries( sourceType .orderedProperties() @@ -670,4 +671,39 @@ export abstract class BaseVisitor implements Visitor { isPublic, } } + + protected getNodeDescription(node: ts.Node): string | null { + const docs = ts.getJSDocCommentsAndTags(node) + for (const doc of docs) { + if (ts.isJSDoc(doc)) { + return ts.getTextOfJSDocComment(doc.comment) ?? null + } + } + return null + } + + protected getMethodDocumentation(node: ts.FunctionDeclaration | ts.MethodDeclaration | ts.ConstructorDeclaration): MethodDocumentation { + const docs = Array.from(ts.getJSDocCommentsAndTags(node)) + let description: string | null = null + const args = new Map() + let returns: string | null = null + for (const doc of docs) { + if (ts.isJSDoc(doc)) { + description = ts.getTextOfJSDocComment(doc.comment) ?? null + if (doc.tags) docs.push(...doc.tags) + } else if (ts.isJSDocParameterTag(doc)) { + const paramName = this.textVisitor.accept(doc.name) + const paramComment = ts.getTextOfJSDocComment(doc.comment) + + args.set(paramName, paramComment ?? '') + } else if (ts.isJSDocReturnTag(doc)) { + returns = ts.getTextOfJSDocComment(doc.comment) ?? null + } + } + return nodeFactory.methodDocumentation({ + description, + args, + returns, + }) + } } diff --git a/src/awst_build/ast-visitors/contract-visitor.ts b/src/awst_build/ast-visitors/contract-visitor.ts index 8ef2911e..687a88a9 100644 --- a/src/awst_build/ast-visitors/contract-visitor.ts +++ b/src/awst_build/ast-visitors/contract-visitor.ts @@ -65,7 +65,7 @@ export class ContractVisitor extends BaseVisitor implements Visitor ContractReference.fromPType(bt)), - description: null, + description: this.getNodeDescription(classDec), approvalProgram: this._contractPType.isARC4 ? null : this._approvalProgram, clearProgram: this._clearStateProgram, reservedScratchSpace: new Set(), @@ -165,7 +165,12 @@ export class ContractVisitor extends BaseVisitor implements Visitor extends InstanceExpressionBuilder { - buildStorageDeclaration(memberName: string, memberLocation: SourceLocation, contractType: ContractClassPType): AppStorageDeclaration { + buildStorageDeclaration( + memberName: string, + memberLocation: SourceLocation, + memberDescription: string | null, + contractType: ContractClassPType, + ): AppStorageDeclaration { codeInvariant( this._expr instanceof BytesConstant, `key${this.ptype instanceof BoxMapPType ? ' prefix' : ''} must be a compile time constant value if ${this.typeDescription} is assigned to a contract member`, @@ -21,7 +26,7 @@ export abstract class BoxProxyExpressionBuilder< ptype: this.ptype, memberName: memberName, keyOverride: this._expr ?? null, - description: null, + description: memberDescription, definedIn: contractType, }) } diff --git a/src/awst_build/eb/storage/global-state.ts b/src/awst_build/eb/storage/global-state.ts index 973049aa..acc26eb8 100644 --- a/src/awst_build/eb/storage/global-state.ts +++ b/src/awst_build/eb/storage/global-state.ts @@ -108,7 +108,12 @@ export class GlobalStateFunctionResultBuilder extends InstanceBuilder readonly sourceLocation: SourceLocation | undefined @@ -109,10 +110,12 @@ export class ARC4StructType extends ARC4EncodedType { name, module, fields, + description, sourceLocation, }: { name: string module: string + description: string | undefined fields: Record sourceLocation?: SourceLocation }) { @@ -120,6 +123,7 @@ export class ARC4StructType extends ARC4EncodedType { this.name = name this.module = module this.fields = fields + this.description = description this.sourceLocation = sourceLocation } @@ -132,6 +136,7 @@ export class ARC4StructType extends ARC4EncodedType { name: this.name, fields: Object.fromEntries(Object.entries(this.fields).map(([f, t]) => [f, t.wtype])), sourceLocation: this.sourceLocation, + desc: this.description ?? null, frozen: false, }) } @@ -154,6 +159,7 @@ export const arc4StructBaseType = new ARC4StructType({ name: 'StructBase', module: Constants.arc4EncodedTypesModuleName, fields: {}, + description: undefined, }) export const Arc4TupleClass = new LibClassType({ diff --git a/src/awst_build/ptypes/index.ts b/src/awst_build/ptypes/index.ts index 094b2798..2998a60a 100644 --- a/src/awst_build/ptypes/index.ts +++ b/src/awst_build/ptypes/index.ts @@ -501,6 +501,7 @@ export class FunctionPType extends PType { name: `${props.name}Result`, module: props.module, properties: props.returnType.properties, + description: props.returnType.description, }) } else { this.returnType = props.returnType @@ -617,12 +618,13 @@ export class ArrayPType extends TransientType { } type ObjectPTypeArgs = - | { module: string; name: string; properties: Record; isAnonymous?: false } - | { module?: undefined; name?: undefined; properties: Record; isAnonymous: true } + | { module: string; name: string; description: string | undefined; properties: Record; isAnonymous?: false } + | { module?: undefined; name?: undefined; properties: Record; isAnonymous: true; description?: undefined } export class ObjectPType extends PType { readonly name: string readonly module: string + readonly description: string | undefined readonly properties: Record readonly singleton = false readonly isAnonymous: boolean @@ -633,6 +635,7 @@ export class ObjectPType extends PType { this.module = props.module ?? '' this.properties = props.properties this.isAnonymous = props.isAnonymous ?? false + this.description = props.description } static anonymous(props: Record | Array<[string, PType]>) { diff --git a/src/awst_build/type-resolver.ts b/src/awst_build/type-resolver.ts index a006c7ae..717a729a 100644 --- a/src/awst_build/type-resolver.ts +++ b/src/awst_build/type-resolver.ts @@ -263,7 +263,6 @@ export class TypeResolver { private reflectObjectType(tsType: ts.Type, sourceLocation: SourceLocation): ObjectPType { const typeAlias = tsType.aliasSymbol ? this.getSymbolFullName(tsType.aliasSymbol, sourceLocation) : undefined - const properties: Record = {} for (const prop of tsType.getProperties()) { if (prop.name.startsWith('__@')) { @@ -280,7 +279,7 @@ export class TypeResolver { } } if (typeAlias) { - return new ObjectPType({ ...typeAlias, properties }) + return new ObjectPType({ ...typeAlias, properties, description: tryGetTypeDescription(tsType) }) } return ObjectPType.anonymous(properties) } @@ -322,13 +321,14 @@ export class TypeResolver { module: typeName.module, }) } + private reflectStructType( typeName: SymbolName, tsType: ts.Type, baseType: ARC4StructType, sourceLocation: SourceLocation, ): ARC4StructType { - const ignoredProps = ['bytes', '__type', 'equals', Constants.constructorMethodName] + const ignoredProps = ['bytes', 'equals', Constants.constructorMethodName] const fields: Record = {} for (const prop of tsType.getProperties()) { if (isIn(prop.name, ignoredProps)) continue @@ -345,6 +345,7 @@ export class TypeResolver { ...typeName, fields: fields, sourceLocation: sourceLocation, + description: tryGetTypeDescription(tsType), }) } @@ -442,3 +443,15 @@ function isIntersectionType(tsType: ts.Type): tsType is ts.IntersectionType { function isInstantiationExpression(tsType: ts.Type): tsType is ts.Type & { node: ts.ExpressionWithTypeArguments } { return isObjectType(tsType) && hasFlags(tsType.objectFlags, ObjectFlags.InstantiationExpressionType) } + +function tryGetTypeDescription(tsType: ts.Type): string | undefined { + const dec = tsType.aliasSymbol?.valueDeclaration ?? tsType.symbol.valueDeclaration + if (!dec) return undefined + const docs = ts.getJSDocCommentsAndTags(dec) + for (const doc of docs) { + if (ts.isJSDoc(doc)) { + return ts.getTextOfJSDocComment(doc.comment) + } + } + return undefined +} diff --git a/tests/approvals/jsdoc.algo.ts b/tests/approvals/jsdoc.algo.ts new file mode 100644 index 00000000..007e6a08 --- /dev/null +++ b/tests/approvals/jsdoc.algo.ts @@ -0,0 +1,44 @@ +import type { bytes, uint64 } from '@algorandfoundation/algorand-typescript' +import { Contract, GlobalState, LocalState } from '@algorandfoundation/algorand-typescript' +import { Struct, UintN } from '@algorandfoundation/algorand-typescript/arc4' + +/** + * This is the description for demo struct + */ +class DemoStruct extends Struct<{ a: UintN<64> }> {} + +/** + * This is the description for demo type + */ +type DemoType = { + a: bytes +} + +/** + * This is the description for the contract + */ +export class JSDocDemo extends Contract { + globalState = GlobalState() + localState = LocalState() + + /** + * This is the description of the method + * @param a This is the description of 'a' + * @param b This is the description of 'b' + * @returns This is the description of the return value + */ + test(a: uint64, b: bytes): DemoStruct { + return new DemoStruct({ a: new UintN<64>(a) }) + } + + /** + * This is the description of the method + * @param a This is the description of 'a' + * @returns This is the description of the return value + */ + test2(a: bytes): DemoType { + return { + a, + } + } +} diff --git a/tests/approvals/out/jsdoc/JSDocDemo.approval.teal b/tests/approvals/out/jsdoc/JSDocDemo.approval.teal new file mode 100644 index 00000000..ad862ea9 --- /dev/null +++ b/tests/approvals/out/jsdoc/JSDocDemo.approval.teal @@ -0,0 +1,118 @@ +#pragma version 10 + +tests/approvals/jsdoc.algo.ts::JSDocDemo.approvalProgram: + intcblock 1 0 + bytecblock 0x151f7c75 + callsub __puya_arc4_router__ + return + + +// tests/approvals/jsdoc.algo.ts::JSDocDemo.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + // tests/approvals/jsdoc.algo.ts:20 + // export class JSDocDemo extends Contract { + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@6 + pushbytess 0x60d93beb 0x6618726a // method "test(uint64,byte[])(uint64)", method "test2(byte[])(byte[])" + txna ApplicationArgs 0 + match __puya_arc4_router___test_route@2 __puya_arc4_router___test2_route@3 + intc_1 // 0 + retsub + +__puya_arc4_router___test_route@2: + // tests/approvals/jsdoc.algo.ts:30 + // test(a: uint64, b: bytes): DemoStruct { + txn OnCompletion + ! + assert // OnCompletion is not NoOp + txn ApplicationID + assert // can only call when not creating + // tests/approvals/jsdoc.algo.ts:20 + // export class JSDocDemo extends Contract { + txna ApplicationArgs 1 + btoi + txna ApplicationArgs 2 + extract 2 0 + // tests/approvals/jsdoc.algo.ts:30 + // test(a: uint64, b: bytes): DemoStruct { + callsub test + bytec_0 // 0x151f7c75 + swap + concat + log + intc_0 // 1 + retsub + +__puya_arc4_router___test2_route@3: + // tests/approvals/jsdoc.algo.ts:39 + // test2(a: bytes): DemoType { + txn OnCompletion + ! + assert // OnCompletion is not NoOp + txn ApplicationID + assert // can only call when not creating + // tests/approvals/jsdoc.algo.ts:20 + // export class JSDocDemo extends Contract { + txna ApplicationArgs 1 + extract 2 0 + // tests/approvals/jsdoc.algo.ts:39 + // test2(a: bytes): DemoType { + callsub test2 + dup + len + itob + extract 6 2 + swap + concat + pushbytes 0x0002 + swap + concat + bytec_0 // 0x151f7c75 + swap + concat + log + intc_0 // 1 + retsub + +__puya_arc4_router___bare_routing@6: + // tests/approvals/jsdoc.algo.ts:20 + // export class JSDocDemo extends Contract { + txn OnCompletion + bnz __puya_arc4_router___after_if_else@10 + txn ApplicationID + ! + assert // can only call when creating + intc_0 // 1 + retsub + +__puya_arc4_router___after_if_else@10: + // tests/approvals/jsdoc.algo.ts:20 + // export class JSDocDemo extends Contract { + intc_1 // 0 + retsub + + +// tests/approvals/jsdoc.algo.ts::JSDocDemo.test(a: uint64, b: bytes) -> bytes: +test: + // tests/approvals/jsdoc.algo.ts:30 + // test(a: uint64, b: bytes): DemoStruct { + proto 2 1 + // tests/approvals/jsdoc.algo.ts:31 + // return new DemoStruct({ a: new UintN<64>(a) }) + frame_dig -2 + itob + retsub + + +// tests/approvals/jsdoc.algo.ts::JSDocDemo.test2(a: bytes) -> bytes: +test2: + // tests/approvals/jsdoc.algo.ts:39 + // test2(a: bytes): DemoType { + proto 1 1 + // tests/approvals/jsdoc.algo.ts:40-42 + // return { + // a, + // } + frame_dig -1 + retsub diff --git a/tests/approvals/out/jsdoc/JSDocDemo.arc32.json b/tests/approvals/out/jsdoc/JSDocDemo.arc32.json new file mode 100644 index 00000000..8fd73b9a --- /dev/null +++ b/tests/approvals/out/jsdoc/JSDocDemo.arc32.json @@ -0,0 +1,116 @@ +{ + "hints": { + "test(uint64,byte[])(uint64)": { + "call_config": { + "no_op": "CALL" + }, + "structs": { + "output": { + "name": "DemoStruct", + "elements": [ + [ + "a", + "uint64" + ] + ] + } + } + }, + "test2(byte[])(byte[])": { + "call_config": { + "no_op": "CALL" + }, + "structs": { + "output": { + "name": "DemoType", + "elements": [ + [ + "a", + "byte[]" + ] + ] + } + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czo6SlNEb2NEZW1vLmFwcHJvdmFsUHJvZ3JhbToKICAgIGludGNibG9jayAxIDAKICAgIGJ5dGVjYmxvY2sgMHgxNTFmN2M3NQogICAgY2FsbHN1YiBfX3B1eWFfYXJjNF9yb3V0ZXJfXwogICAgcmV0dXJuCgoKLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6OkpTRG9jRGVtby5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czoyMAogICAgLy8gZXhwb3J0IGNsYXNzIEpTRG9jRGVtbyBleHRlbmRzIENvbnRyYWN0IHsKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBwdXNoYnl0ZXNzIDB4NjBkOTNiZWIgMHg2NjE4NzI2YSAvLyBtZXRob2QgInRlc3QodWludDY0LGJ5dGVbXSkodWludDY0KSIsIG1ldGhvZCAidGVzdDIoYnl0ZVtdKShieXRlW10pIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fdGVzdF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3Rlc3QyX3JvdXRlQDMKICAgIGludGNfMSAvLyAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX3Rlc3Rfcm91dGVAMjoKICAgIC8vIHRlc3RzL2FwcHJvdmFscy9qc2RvYy5hbGdvLnRzOjMwCiAgICAvLyB0ZXN0KGE6IHVpbnQ2NCwgYjogYnl0ZXMpOiBEZW1vU3RydWN0IHsKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6MjAKICAgIC8vIGV4cG9ydCBjbGFzcyBKU0RvY0RlbW8gZXh0ZW5kcyBDb250cmFjdCB7CiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBidG9pCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBleHRyYWN0IDIgMAogICAgLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6MzAKICAgIC8vIHRlc3QoYTogdWludDY0LCBiOiBieXRlcyk6IERlbW9TdHJ1Y3QgewogICAgY2FsbHN1YiB0ZXN0CiAgICBieXRlY18wIC8vIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnRjXzAgLy8gMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX190ZXN0Ml9yb3V0ZUAzOgogICAgLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6MzkKICAgIC8vIHRlc3QyKGE6IGJ5dGVzKTogRGVtb1R5cGUgewogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czoyMAogICAgLy8gZXhwb3J0IGNsYXNzIEpTRG9jRGVtbyBleHRlbmRzIENvbnRyYWN0IHsKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGV4dHJhY3QgMiAwCiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czozOQogICAgLy8gdGVzdDIoYTogYnl0ZXMpOiBEZW1vVHlwZSB7CiAgICBjYWxsc3ViIHRlc3QyCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgcHVzaGJ5dGVzIDB4MDAwMgogICAgc3dhcAogICAgY29uY2F0CiAgICBieXRlY18wIC8vIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnRjXzAgLy8gMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIC8vIHRlc3RzL2FwcHJvdmFscy9qc2RvYy5hbGdvLnRzOjIwCiAgICAvLyBleHBvcnQgY2xhc3MgSlNEb2NEZW1vIGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIGNyZWF0aW5nCiAgICBpbnRjXzAgLy8gMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6MjAKICAgIC8vIGV4cG9ydCBjbGFzcyBKU0RvY0RlbW8gZXh0ZW5kcyBDb250cmFjdCB7CiAgICBpbnRjXzEgLy8gMAogICAgcmV0c3ViCgoKLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6OkpTRG9jRGVtby50ZXN0KGE6IHVpbnQ2NCwgYjogYnl0ZXMpIC0+IGJ5dGVzOgp0ZXN0OgogICAgLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6MzAKICAgIC8vIHRlc3QoYTogdWludDY0LCBiOiBieXRlcyk6IERlbW9TdHJ1Y3QgewogICAgcHJvdG8gMiAxCiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czozMQogICAgLy8gcmV0dXJuIG5ldyBEZW1vU3RydWN0KHsgYTogbmV3IFVpbnROPDY0PihhKSB9KQogICAgZnJhbWVfZGlnIC0yCiAgICBpdG9iCiAgICByZXRzdWIKCgovLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czo6SlNEb2NEZW1vLnRlc3QyKGE6IGJ5dGVzKSAtPiBieXRlczoKdGVzdDI6CiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czozOQogICAgLy8gdGVzdDIoYTogYnl0ZXMpOiBEZW1vVHlwZSB7CiAgICBwcm90byAxIDEKICAgIC8vIHRlc3RzL2FwcHJvdmFscy9qc2RvYy5hbGdvLnRzOjQwLTQyCiAgICAvLyByZXR1cm4gewogICAgLy8gICBhLAogICAgLy8gfQogICAgZnJhbWVfZGlnIC0xCiAgICByZXRzdWIK", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czo6SlNEb2NEZW1vLmNsZWFyU3RhdGVQcm9ncmFtOgogICAgcHVzaGludCAxIC8vIDEKICAgIHJldHVybgo=" + }, + "state": { + "global": { + "num_byte_slices": 1, + "num_uints": 1 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": { + "globalState": { + "type": "bytes", + "key": "globalState" + }, + "localState": { + "type": "uint64", + "key": "localState" + } + }, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "JSDocDemo", + "desc": "This is the description for the contract", + "methods": [ + { + "name": "test", + "args": [ + { + "type": "uint64", + "name": "a", + "desc": "This is the description of 'a'" + }, + { + "type": "byte[]", + "name": "b", + "desc": "This is the description of 'b'" + } + ], + "readonly": false, + "returns": { + "type": "(uint64)", + "desc": "This is the description of the return value" + }, + "desc": "This is the description of the method" + }, + { + "name": "test2", + "args": [ + { + "type": "byte[]", + "name": "a", + "desc": "This is the description of 'a'" + } + ], + "readonly": false, + "returns": { + "type": "(byte[])", + "desc": "This is the description of the return value" + }, + "desc": "This is the description of the method" + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/tests/approvals/out/jsdoc/JSDocDemo.arc56.json b/tests/approvals/out/jsdoc/JSDocDemo.arc56.json new file mode 100644 index 00000000..612c0649 --- /dev/null +++ b/tests/approvals/out/jsdoc/JSDocDemo.arc56.json @@ -0,0 +1,156 @@ +{ + "name": "JSDocDemo", + "structs": { + "DemoStruct": [ + { + "name": "a", + "type": "uint64" + } + ], + "DemoType": [ + { + "name": "a", + "type": "byte[]" + } + ] + }, + "methods": [ + { + "name": "test", + "args": [ + { + "type": "uint64", + "name": "a", + "desc": "This is the description of 'a'" + }, + { + "type": "byte[]", + "name": "b", + "desc": "This is the description of 'b'" + } + ], + "returns": { + "type": "(uint64)", + "struct": "DemoStruct", + "desc": "This is the description of the return value" + }, + "actions": { + "create": [], + "call": [ + "NoOp" + ] + }, + "readonly": false, + "desc": "This is the description of the method", + "events": [], + "recommendations": {} + }, + { + "name": "test2", + "args": [ + { + "type": "byte[]", + "name": "a", + "desc": "This is the description of 'a'" + } + ], + "returns": { + "type": "(byte[])", + "struct": "DemoType", + "desc": "This is the description of the return value" + }, + "actions": { + "create": [], + "call": [ + "NoOp" + ] + }, + "readonly": false, + "desc": "This is the description of the method", + "events": [], + "recommendations": {} + } + ], + "arcs": [ + 22, + 28 + ], + "desc": "This is the description for the contract", + "networks": {}, + "state": { + "schema": { + "global": { + "ints": 1, + "bytes": 1 + }, + "local": { + "ints": 0, + "bytes": 0 + } + }, + "keys": { + "global": { + "globalState": { + "keyType": "AVMString", + "valueType": "AVMString", + "key": "Z2xvYmFsU3RhdGU=" + }, + "localState": { + "keyType": "AVMString", + "valueType": "AVMUint64", + "key": "bG9jYWxTdGF0ZQ==" + } + }, + "local": {}, + "box": {} + }, + "maps": { + "global": {}, + "local": {}, + "box": {} + } + }, + "bareActions": { + "create": [ + "NoOp" + ], + "call": [] + }, + "sourceInfo": { + "approval": { + "sourceInfo": [ + { + "pc": [ + 50, + 76 + ], + "errorMessage": "OnCompletion is not NoOp" + }, + { + "pc": [ + 117 + ], + "errorMessage": "can only call when creating" + }, + { + "pc": [ + 53, + 79 + ], + "errorMessage": "can only call when not creating" + } + ], + "pcOffsetMethod": "none" + }, + "clear": { + "sourceInfo": [], + "pcOffsetMethod": "none" + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czo6SlNEb2NEZW1vLmFwcHJvdmFsUHJvZ3JhbToKICAgIGludGNibG9jayAxIDAKICAgIGJ5dGVjYmxvY2sgMHgxNTFmN2M3NQogICAgY2FsbHN1YiBfX3B1eWFfYXJjNF9yb3V0ZXJfXwogICAgcmV0dXJuCgoKLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6OkpTRG9jRGVtby5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czoyMAogICAgLy8gZXhwb3J0IGNsYXNzIEpTRG9jRGVtbyBleHRlbmRzIENvbnRyYWN0IHsKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBwdXNoYnl0ZXNzIDB4NjBkOTNiZWIgMHg2NjE4NzI2YSAvLyBtZXRob2QgInRlc3QodWludDY0LGJ5dGVbXSkodWludDY0KSIsIG1ldGhvZCAidGVzdDIoYnl0ZVtdKShieXRlW10pIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fdGVzdF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3Rlc3QyX3JvdXRlQDMKICAgIGludGNfMSAvLyAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX3Rlc3Rfcm91dGVAMjoKICAgIC8vIHRlc3RzL2FwcHJvdmFscy9qc2RvYy5hbGdvLnRzOjMwCiAgICAvLyB0ZXN0KGE6IHVpbnQ2NCwgYjogYnl0ZXMpOiBEZW1vU3RydWN0IHsKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6MjAKICAgIC8vIGV4cG9ydCBjbGFzcyBKU0RvY0RlbW8gZXh0ZW5kcyBDb250cmFjdCB7CiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBidG9pCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBleHRyYWN0IDIgMAogICAgLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6MzAKICAgIC8vIHRlc3QoYTogdWludDY0LCBiOiBieXRlcyk6IERlbW9TdHJ1Y3QgewogICAgY2FsbHN1YiB0ZXN0CiAgICBieXRlY18wIC8vIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnRjXzAgLy8gMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX190ZXN0Ml9yb3V0ZUAzOgogICAgLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6MzkKICAgIC8vIHRlc3QyKGE6IGJ5dGVzKTogRGVtb1R5cGUgewogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czoyMAogICAgLy8gZXhwb3J0IGNsYXNzIEpTRG9jRGVtbyBleHRlbmRzIENvbnRyYWN0IHsKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGV4dHJhY3QgMiAwCiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czozOQogICAgLy8gdGVzdDIoYTogYnl0ZXMpOiBEZW1vVHlwZSB7CiAgICBjYWxsc3ViIHRlc3QyCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgcHVzaGJ5dGVzIDB4MDAwMgogICAgc3dhcAogICAgY29uY2F0CiAgICBieXRlY18wIC8vIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnRjXzAgLy8gMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIC8vIHRlc3RzL2FwcHJvdmFscy9qc2RvYy5hbGdvLnRzOjIwCiAgICAvLyBleHBvcnQgY2xhc3MgSlNEb2NEZW1vIGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIGNyZWF0aW5nCiAgICBpbnRjXzAgLy8gMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6MjAKICAgIC8vIGV4cG9ydCBjbGFzcyBKU0RvY0RlbW8gZXh0ZW5kcyBDb250cmFjdCB7CiAgICBpbnRjXzEgLy8gMAogICAgcmV0c3ViCgoKLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6OkpTRG9jRGVtby50ZXN0KGE6IHVpbnQ2NCwgYjogYnl0ZXMpIC0+IGJ5dGVzOgp0ZXN0OgogICAgLy8gdGVzdHMvYXBwcm92YWxzL2pzZG9jLmFsZ28udHM6MzAKICAgIC8vIHRlc3QoYTogdWludDY0LCBiOiBieXRlcyk6IERlbW9TdHJ1Y3QgewogICAgcHJvdG8gMiAxCiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czozMQogICAgLy8gcmV0dXJuIG5ldyBEZW1vU3RydWN0KHsgYTogbmV3IFVpbnROPDY0PihhKSB9KQogICAgZnJhbWVfZGlnIC0yCiAgICBpdG9iCiAgICByZXRzdWIKCgovLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czo6SlNEb2NEZW1vLnRlc3QyKGE6IGJ5dGVzKSAtPiBieXRlczoKdGVzdDI6CiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czozOQogICAgLy8gdGVzdDIoYTogYnl0ZXMpOiBEZW1vVHlwZSB7CiAgICBwcm90byAxIDEKICAgIC8vIHRlc3RzL2FwcHJvdmFscy9qc2RvYy5hbGdvLnRzOjQwLTQyCiAgICAvLyByZXR1cm4gewogICAgLy8gICBhLAogICAgLy8gfQogICAgZnJhbWVfZGlnIC0xCiAgICByZXRzdWIK", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0cy9hcHByb3ZhbHMvanNkb2MuYWxnby50czo6SlNEb2NEZW1vLmNsZWFyU3RhdGVQcm9ncmFtOgogICAgcHVzaGludCAxIC8vIDEKICAgIHJldHVybgo=" + }, + "events": [], + "templateVariables": {} +} \ No newline at end of file diff --git a/tests/approvals/out/jsdoc/JSDocDemo.clear.teal b/tests/approvals/out/jsdoc/JSDocDemo.clear.teal new file mode 100644 index 00000000..8054cedd --- /dev/null +++ b/tests/approvals/out/jsdoc/JSDocDemo.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +tests/approvals/jsdoc.algo.ts::JSDocDemo.clearStateProgram: + pushint 1 // 1 + return diff --git a/tests/approvals/out/jsdoc/JSDocDemo.ssa.ir b/tests/approvals/out/jsdoc/JSDocDemo.ssa.ir new file mode 100644 index 00000000..f26cca6e --- /dev/null +++ b/tests/approvals/out/jsdoc/JSDocDemo.ssa.ir @@ -0,0 +1,105 @@ +contract tests/approvals/jsdoc.algo.ts::JSDocDemo: + program approval: + subroutine @algorandfoundation/algorand-typescript/arc4/index.d.ts::Contract.approvalProgram() -> bool: + block@0: // L1 + let reinterpret_bool%0#0: bool = (txn ApplicationID) + goto reinterpret_bool%0#0 ? block@2 : block@1 + block@1: // if_body_L1 + tests/approvals/jsdoc.algo.ts::JSDocDemo.constructor() + goto block@2 + block@2: // after_if_else_L1 + let tmp%0#0: bool = tests/approvals/jsdoc.algo.ts::JSDocDemo.__puya_arc4_router__() + return tmp%0#0 + + subroutine tests/approvals/jsdoc.algo.ts::JSDocDemo.constructor() -> void: + block@0: // L20 + return + + subroutine tests/approvals/jsdoc.algo.ts::JSDocDemo.__puya_arc4_router__() -> bool: + block@0: // L20 + let tmp%0#0: uint64 = (txn NumAppArgs) + let tmp%1#0: bool = (!= tmp%0#0 0u) + goto tmp%1#0 ? block@1 : block@6 + block@1: // abi_routing_L20 + let tmp%2#0: bytes = (txna ApplicationArgs 0) + switch tmp%2#0 {method "test(uint64,byte[])(uint64)" => block@2, method "test2(byte[])(byte[])" => block@3, * => block@4} + block@2: // test_route_L30 + let tmp%3#0: uint64 = (txn OnCompletion) + let tmp%4#0: bool = (== tmp%3#0 NoOp) + (assert tmp%4#0) // OnCompletion is not NoOp + let tmp%5#0: uint64 = (txn ApplicationID) + let tmp%6#0: bool = (!= tmp%5#0 0u) + (assert tmp%6#0) // can only call when not creating + let tmp%7#0: bytes = (txna ApplicationArgs 1) + let tmp%8#0: uint64 = (btoi tmp%7#0) + let tmp%9#0: bytes = (txna ApplicationArgs 2) + let tmp%10#0: bytes = ((extract 2 0) tmp%9#0) + let tmp%11#0: bytes = tests/approvals/jsdoc.algo.ts::JSDocDemo.test(tmp%8#0, tmp%10#0) + let tmp%12#0: bytes = (concat 0x151f7c75 tmp%11#0) + (log tmp%12#0) + return 1u + block@3: // test2_route_L39 + let tmp%13#0: uint64 = (txn OnCompletion) + let tmp%14#0: bool = (== tmp%13#0 NoOp) + (assert tmp%14#0) // OnCompletion is not NoOp + let tmp%15#0: uint64 = (txn ApplicationID) + let tmp%16#0: bool = (!= tmp%15#0 0u) + (assert tmp%16#0) // can only call when not creating + let tmp%17#0: bytes = (txna ApplicationArgs 1) + let tmp%18#0: bytes = ((extract 2 0) tmp%17#0) + let elements_to_encode%0#0: bytes = tests/approvals/jsdoc.algo.ts::JSDocDemo.test2(tmp%18#0) + let length%0#0: uint64 = (len elements_to_encode%0#0) + let as_bytes%0#0: bytes = (itob length%0#0) + let length_uint16%0#0: bytes = ((extract 6 2) as_bytes%0#0) + let encoded_value%0#0: bytes = (concat length_uint16%0#0 elements_to_encode%0#0) + let current_tail_offset%0#0: uint64 = 2u + let encoded_tuple_buffer%0#0: bytes = 0x + let as_bytes%1#0: bytes = (itob current_tail_offset%0#0) + let offset_as_uint16%0#0: bytes = ((extract 6 2) as_bytes%1#0) + let encoded_tuple_buffer%1#0: bytes = (concat encoded_tuple_buffer%0#0 offset_as_uint16%0#0) + let data_length%0#0: uint64 = (len encoded_value%0#0) + let current_tail_offset%1#0: uint64 = (+ current_tail_offset%0#0 data_length%0#0) + let encoded_tuple_buffer%2#0: bytes = (concat encoded_tuple_buffer%1#0 encoded_value%0#0) + let tmp%19#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) + (log tmp%19#0) + return 1u + block@4: // switch_case_default_L20 + goto block@5 + block@5: // switch_case_next_L20 + goto block@10 + block@6: // bare_routing_L20 + let tmp%20#0: uint64 = (txn OnCompletion) + switch tmp%20#0 {0u => block@7, * => block@8} + block@7: // __algots__.defaultCreate_L20 + let tmp%21#0: uint64 = (txn ApplicationID) + let tmp%22#0: bool = (== tmp%21#0 0u) + (assert tmp%22#0) // can only call when creating + tests/approvals/jsdoc.algo.ts::JSDocDemo.__algots__.defaultCreate() + return 1u + block@8: // switch_case_default_L20 + goto block@9 + block@9: // switch_case_next_L20 + goto block@10 + block@10: // after_if_else_L20 + return 0u + + subroutine tests/approvals/jsdoc.algo.ts::JSDocDemo.test(a: uint64, b: bytes) -> bytes: + block@0: // L30 + let val_as_bytes%0#0: bytes = (itob a#0) + let current_tail_offset%0#0: uint64 = 8u + let encoded_tuple_buffer%0#0: bytes = 0x + let encoded_tuple_buffer%1#0: bytes = (concat encoded_tuple_buffer%0#0 val_as_bytes%0#0) + return encoded_tuple_buffer%1#0 + + subroutine tests/approvals/jsdoc.algo.ts::JSDocDemo.test2(a: bytes) -> bytes: + block@0: // L39 + return a#0 + + subroutine tests/approvals/jsdoc.algo.ts::JSDocDemo.__algots__.defaultCreate() -> void: + block@0: // L20 + return + + program clear-state: + subroutine @algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract.clearStateProgram() -> bool: + block@0: // L1 + return 1u \ No newline at end of file diff --git a/tests/approvals/out/jsdoc/jsdoc.awst b/tests/approvals/out/jsdoc/jsdoc.awst new file mode 100644 index 00000000..130a1fb1 --- /dev/null +++ b/tests/approvals/out/jsdoc/jsdoc.awst @@ -0,0 +1,48 @@ +contract JSDocDemo +{ + globals { + ["globalState"]: string + ["localState"]: uint64 + } + approvalProgram(): bool + { + if (!Boolean(txn())) { + this.constructor() + } + return arc4Router() + } + + clearProgram(): bool + { + return True + } + + test(): DemoStruct + { + return new DemoStruct(a=(#0 = { a: ARC4_ENCODE(a, wtype=arc4.uint64) }).a) + } + + test2(): DemoType{ a: bytes } + { + return { a: (#1 = { a: a }).a } + } + + constructor(): void + { + void + } + + Contract::constructor(): void + { + } + + Contract::constructor(): void + { + this.constructor() + } + + __algots__.defaultCreate(): void + { + } + +} \ No newline at end of file diff --git a/tests/approvals/out/jsdoc/jsdoc.awst.json b/tests/approvals/out/jsdoc/jsdoc.awst.json new file mode 100644 index 00000000..2e56509d --- /dev/null +++ b/tests/approvals/out/jsdoc/jsdoc.awst.json @@ -0,0 +1,1218 @@ +[ + { + "_type": "Contract", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 20, + "end_line": 20, + "column": 0, + "end_column": 41 + }, + "id": "tests/approvals/jsdoc.algo.ts::JSDocDemo", + "name": "JSDocDemo", + "description": "This is the description for the contract", + "method_resolution_order": [ + "@algorandfoundation/algorand-typescript/arc4/index.d.ts::Contract", + "@algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract" + ], + "approval_program": { + "_type": "ContractMethod", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "body": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "IfElse", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "condition": { + "_type": "Not", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "expr": { + "_type": "ReinterpretCast", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "op_code": "txn", + "immediates": [ + "ApplicationID" + ], + "stack_args": [] + } + } + }, + "if_branch": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "expr": { + "_type": "SubroutineCallExpression", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "target": { + "_type": "InstanceMethodTarget", + "member_name": "constructor" + }, + "args": [] + } + } + ], + "label": null, + "comment": null + }, + "else_branch": null + }, + { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "ReturnStatement", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "value": { + "_type": "ARC4Router", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + } + } + } + ], + "label": null, + "comment": null + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "@algorandfoundation/algorand-typescript/arc4/index.d.ts::Contract", + "member_name": "approvalProgram", + "arc4_method_config": null + }, + "clear_program": { + "_type": "ContractMethod", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "body": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "ReturnStatement", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "value": { + "_type": "BoolConstant", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": true + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "@algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract", + "member_name": "clearStateProgram", + "arc4_method_config": null + }, + "methods": [ + { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 30, + "end_line": 30, + "column": 2, + "end_column": 39 + }, + "args": [ + { + "_type": "SubroutineArgument", + "name": "a", + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 30, + "end_line": 30, + "column": 7, + "end_column": 16 + } + }, + { + "_type": "SubroutineArgument", + "name": "b", + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 30, + "end_line": 30, + "column": 18, + "end_column": 26 + } + } + ], + "return_type": { + "_type": "ARC4Struct", + "name": "DemoStruct", + "immutable": true, + "ephemeral": false, + "scalar_type": 1, + "native_type": null, + "arc4_name": "uint64", + "fields": { + "a": { + "_type": "ARC4UIntN", + "name": "arc4.uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 1, + "native_type": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "arc4_name": "uint64", + "n": "64" + } + }, + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 30, + "end_line": 30, + "column": 2, + "end_column": 39 + }, + "frozen": false, + "desc": "This is the description for demo struct" + }, + "body": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 30, + "end_line": 32, + "column": 40, + "end_column": 3 + }, + "body": [ + { + "_type": "ReturnStatement", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 31, + "end_line": 31, + "column": 4, + "end_column": 50 + }, + "value": { + "_type": "NewStruct", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 31, + "end_line": 31, + "column": 11, + "end_column": 50 + }, + "wtype": { + "_type": "ARC4Struct", + "name": "DemoStruct", + "immutable": true, + "ephemeral": false, + "scalar_type": 1, + "native_type": null, + "arc4_name": "uint64", + "fields": { + "a": { + "_type": "ARC4UIntN", + "name": "arc4.uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 1, + "native_type": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "arc4_name": "uint64", + "n": "64" + } + }, + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 31, + "end_line": 31, + "column": 15, + "end_column": 25 + }, + "frozen": false, + "desc": "This is the description for demo struct" + }, + "values": { + "a": { + "_type": "FieldExpression", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 31, + "end_line": 31, + "column": 11, + "end_column": 50 + }, + "wtype": { + "_type": "ARC4UIntN", + "name": "arc4.uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 1, + "native_type": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "arc4_name": "uint64", + "n": "64" + }, + "base": { + "_type": "SingleEvaluation", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 31, + "end_line": 31, + "column": 26, + "end_column": 49 + }, + "wtype": { + "_type": "WTuple", + "name": "::", + "immutable": true, + "ephemeral": false, + "scalar_type": null, + "types": [ + { + "_type": "ARC4UIntN", + "name": "arc4.uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 1, + "native_type": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "arc4_name": "uint64", + "n": "64" + } + ], + "names": [ + "a" + ] + }, + "source": { + "_type": "TupleExpression", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 31, + "end_line": 31, + "column": 26, + "end_column": 49 + }, + "wtype": { + "_type": "WTuple", + "name": "::", + "immutable": true, + "ephemeral": false, + "scalar_type": null, + "types": [ + { + "_type": "ARC4UIntN", + "name": "arc4.uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 1, + "native_type": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "arc4_name": "uint64", + "n": "64" + } + ], + "names": [ + "a" + ] + }, + "items": [ + { + "_type": "ARC4Encode", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 31, + "end_line": 31, + "column": 31, + "end_column": 47 + }, + "wtype": { + "_type": "ARC4UIntN", + "name": "arc4.uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 1, + "native_type": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "arc4_name": "uint64", + "n": "64" + }, + "value": { + "_type": "VarExpression", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 31, + "end_line": 31, + "column": 45, + "end_column": 46 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "name": "a" + } + } + ] + }, + "id": "0" + }, + "name": "a" + } + } + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": "This is the description of the method", + "args": { + "a": "This is the description of 'a'", + "b": "This is the description of 'b'" + }, + "returns": "This is the description of the return value" + }, + "cref": "tests/approvals/jsdoc.algo.ts::JSDocDemo", + "member_name": "test", + "arc4_method_config": { + "_type": "ARC4ABIMethodConfig", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 30, + "end_line": 30, + "column": 2, + "end_column": 39 + }, + "name": "test", + "is_bare": false, + "create": 3, + "readonly": false, + "allowed_completion_types": [ + 0 + ], + "default_args": {}, + "structs": { + "output": { + "name": "DemoStruct", + "elements": [ + [ + "a", + "uint64" + ] + ] + } + } + } + }, + { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 39, + "end_line": 39, + "column": 2, + "end_column": 27 + }, + "args": [ + { + "_type": "SubroutineArgument", + "name": "a", + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 39, + "end_line": 39, + "column": 8, + "end_column": 16 + } + } + ], + "return_type": { + "_type": "WTuple", + "name": "tests/approvals/jsdoc.algo.ts::DemoType", + "immutable": true, + "ephemeral": false, + "scalar_type": null, + "types": [ + { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + } + ], + "names": [ + "a" + ] + }, + "body": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 39, + "end_line": 43, + "column": 28, + "end_column": 3 + }, + "body": [ + { + "_type": "ReturnStatement", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 40, + "end_line": 42, + "column": 4, + "end_column": 5 + }, + "value": { + "_type": "TupleExpression", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 40, + "end_line": 42, + "column": 11, + "end_column": 5 + }, + "wtype": { + "_type": "WTuple", + "name": "tests/approvals/jsdoc.algo.ts::DemoType", + "immutable": true, + "ephemeral": false, + "scalar_type": null, + "types": [ + { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + } + ], + "names": [ + "a" + ] + }, + "items": [ + { + "_type": "FieldExpression", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 40, + "end_line": 42, + "column": 11, + "end_column": 5 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "base": { + "_type": "SingleEvaluation", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 40, + "end_line": 42, + "column": 11, + "end_column": 5 + }, + "wtype": { + "_type": "WTuple", + "name": "::", + "immutable": true, + "ephemeral": false, + "scalar_type": null, + "types": [ + { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + } + ], + "names": [ + "a" + ] + }, + "source": { + "_type": "TupleExpression", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 40, + "end_line": 42, + "column": 11, + "end_column": 5 + }, + "wtype": { + "_type": "WTuple", + "name": "::", + "immutable": true, + "ephemeral": false, + "scalar_type": null, + "types": [ + { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + } + ], + "names": [ + "a" + ] + }, + "items": [ + { + "_type": "VarExpression", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 41, + "end_line": 41, + "column": 6, + "end_column": 7 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "name": "a" + } + ] + }, + "id": "1" + }, + "name": "a" + } + ] + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": "This is the description of the method", + "args": { + "a": "This is the description of 'a'" + }, + "returns": "This is the description of the return value" + }, + "cref": "tests/approvals/jsdoc.algo.ts::JSDocDemo", + "member_name": "test2", + "arc4_method_config": { + "_type": "ARC4ABIMethodConfig", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 39, + "end_line": 39, + "column": 2, + "end_column": 27 + }, + "name": "test2", + "is_bare": false, + "create": 3, + "readonly": false, + "allowed_completion_types": [ + 0 + ], + "default_args": {}, + "structs": { + "output": { + "name": "DemoType", + "elements": [ + [ + "a", + "byte[]" + ] + ] + } + } + } + }, + { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 20, + "end_line": 20, + "column": 0, + "end_column": 41 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 20, + "end_line": 20, + "column": 0, + "end_column": 41 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 20, + "end_line": 20, + "column": 0, + "end_column": 41 + }, + "expr": { + "_type": "VoidConstant", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 20, + "end_line": 20, + "column": 0, + "end_column": 41 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + } + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "tests/approvals/jsdoc.algo.ts::JSDocDemo", + "member_name": "constructor", + "arc4_method_config": null + }, + { + "_type": "ContractMethod", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "@algorandfoundation/algorand-typescript/arc4/index.d.ts::Contract", + "member_name": "constructor", + "arc4_method_config": null + }, + { + "_type": "ContractMethod", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "expr": { + "_type": "SubroutineCallExpression", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "target": { + "_type": "InstanceMethodTarget", + "member_name": "constructor" + }, + "args": [] + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "@algorandfoundation/algorand-typescript/arc4/index.d.ts::Contract", + "member_name": "constructor", + "arc4_method_config": null + }, + { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 20, + "end_line": 20, + "column": 0, + "end_column": 41 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 20, + "end_line": 20, + "column": 0, + "end_column": 41 + }, + "body": [], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": "Implicitly generated create method", + "args": {}, + "returns": null + }, + "cref": "tests/approvals/jsdoc.algo.ts::JSDocDemo", + "member_name": "__algots__.defaultCreate", + "arc4_method_config": { + "_type": "ARC4BareMethodConfig", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 20, + "end_line": 20, + "column": 0, + "end_column": 41 + }, + "allowed_completion_types": [ + 0 + ], + "create": 2, + "is_bare": true + } + } + ], + "app_state": [ + { + "_type": "AppStorageDefinition", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 21, + "end_line": 21, + "column": 2, + "end_column": 13 + }, + "member_name": "globalState", + "kind": 1, + "storage_wtype": { + "_type": "WType", + "name": "string", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "key_wtype": null, + "key": { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 21, + "end_line": 21, + "column": 2, + "end_column": 13 + }, + "wtype": { + "_type": "WType", + "name": "state_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "XKZg`VQf=$VRU5", + "encoding": "utf8" + }, + "description": null + }, + { + "_type": "AppStorageDefinition", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 22, + "end_line": 22, + "column": 2, + "end_column": 12 + }, + "member_name": "localState", + "kind": 1, + "storage_wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "key_wtype": null, + "key": { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/jsdoc.algo.ts", + "line": 22, + "end_line": 22, + "column": 2, + "end_column": 12 + }, + "wtype": { + "_type": "WType", + "name": "state_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "Y;R*>Y*Tb$bY%", + "encoding": "utf8" + }, + "description": null + } + ], + "state_totals": { + "globalBytes": null, + "globalUints": null, + "localBytes": null, + "localUints": null + }, + "reserved_scratch_space": [], + "avm_version": null + } +] \ No newline at end of file