Skip to content

Commit

Permalink
Add support for default value in Module Interface (#121)
Browse files Browse the repository at this point in the history
* Add support for default value in Module Interface
  • Loading branch information
miku1958 authored Apr 24, 2024
1 parent b39559a commit 1303b05
Show file tree
Hide file tree
Showing 13 changed files with 113 additions and 7 deletions.
11 changes: 11 additions & 0 deletions demo/basic/generated/kotlin/IHtmlApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ interface IHtmlApiBridge {
fun getName(callback: Callback<IHtmlApiGetNameReturnType>)
fun getAge(gender: IHtmlApiGetAgeGender, callback: Callback<IHtmlApiGetAgeReturnType>)
fun testDictionaryWithAnyKey(dict: Map<String, String>)
fun testDefaultValue(bool: Boolean? = null, bool2: Boolean?, bool3: Boolean = true, num: Float = 1, string: String = "hello")
}

open class IHtmlApiBridge(editor: WebEditor, gson: Gson) : JsBridge(editor, gson, "htmlApi"), IHtmlApiBridge {
Expand Down Expand Up @@ -86,6 +87,16 @@ open class IHtmlApiBridge(editor: WebEditor, gson: Gson) : JsBridge(editor, gson
"dict" to dict
))
}

override fun testDefaultValue(bool: Boolean? = null, bool2: Boolean?, bool3: Boolean = true, num: Float = 1, string: String = "hello") {
executeJs("testDefaultValue", mapOf(
"bool" to bool
"bool2" to bool2
"bool3" to bool3
"num" to num
"string" to string
))
}
}

data class JSBaseSize(
Expand Down
18 changes: 18 additions & 0 deletions demo/basic/generated/swift/IHtmlApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@ public class IHtmlApi {
)
jsExecutor.execute(with: "htmlApi", feature: "testDictionaryWithAnyKey", args: args, completion: completion)
}

public func testDefaultValue(bool: Bool? = nil, bool2: Bool?, bool3: Bool = true, num: Double = 1, string: String = "hello", completion: BridgeJSExecutor.Completion? = nil) {
struct Args: Encodable {
let bool: Bool?
let bool2: Bool?
let bool3: Bool
let num: Double
let string: String
}
let args = Args(
bool: bool,
bool2: bool2,
bool3: bool3,
num: num,
string: string
)
jsExecutor.execute(with: "htmlApi", feature: "testDefaultValue", args: args, completion: completion)
}
}

public struct BaseSize: Codable {
Expand Down
20 changes: 20 additions & 0 deletions demo/basic/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,26 @@ export interface IHtmlApi {
getName(): 'A2' | 'B2';
getAge({ gender }: { gender: 'Male' | 'Female' }): 21 | 22;
testDictionaryWithAnyKey({ dict }: { dict: DictionaryWithAnyKey }): void;

testDefaultValue(options: {
/**
* @default null
*/
bool?: boolean;
bool2?: boolean;
/**
* @default true
*/
bool3: boolean;
/**
* @default 1
*/
num: number;
/**
* @default "hello"
*/
string: string;
}): void;
}

/**
Expand Down
13 changes: 13 additions & 0 deletions documentation/interface-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ ts-gyb parses tags in [JSDoc](https://jsdoc.app) documentation.
- `@shouldExport`: Specify whether an `interface` should be exported. Set it to `true` to export.
- `@overrideModuleName`: Change the name of the interface for ts-gyb. This is helpful for dropping the `I` prefix in TypeScript interface name.
- `@overrideTypeName`: Similar to `@overrideModuleName`, this is used to override the name of custom types used in method parameters or return values.
- `@default`: default value for Module Interface's function parameter,
```typescript
/**
Expand All @@ -225,6 +226,18 @@ ts-gyb parses tags in [JSDoc](https://jsdoc.app) documentation.
interface InterfaceWithTags {
// The name of the module would be `ProperNamedInterface` in generated code
...

foo(bar: {
/**
* @default null
*/
bool?: boolean;
bool2?: boolean;
/**
* @default 1
*/
num: number;
}): void;
}
```

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-gyb",
"version": "0.10.1",
"version": "0.11.0",
"description": "Generate Native API based on TS interface",
"repository": {
"type": "git",
Expand Down
26 changes: 24 additions & 2 deletions src/parser/ValueParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export class ValueParser {
const documentation = ts.displayPartsToString(symbol?.getDocumentationComment(this.checker));

const staticValue = this.parseLiteralNode(node.type);

if (staticValue !== null) {
return { name, type: staticValue.type, staticValue: staticValue.value, documentation };
}
Expand All @@ -155,11 +156,32 @@ export class ValueParser {

const valueType = this.valueTypeFromNode(node);

return {
const jsDocTags = symbol?.getJsDocTags(this.checker);
let defaultValue: string | undefined;
jsDocTags?.forEach((tag) => {
if (tag.name === 'default') {
if (tag.text?.length !== 1 || tag.text[0].kind !== 'text' || tag.text[0].text.length === 0) {
throw new ValueParserError(
`Invalid default value for ${name}`,
'Default value must be a single value, like `@default 0` or `@default "hello"`'
);
}
defaultValue = tag.text[0].text;
}
});

const field: Field = {
name,
type: valueType,
documentation,
documentation
};

if (defaultValue != null) {
// to fix test fail
field.defaultValue = defaultValue;
}

return field;
}

private parseTypeLiteralNode(typeNode: ts.TypeNode): TupleType | DictionaryType | null {
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ export function renderCode<View>(templatePath: string, view: View): string {
return Mustache.render(template, view, (partialName) => {
const partialPath = path.join(directory, `${partialName}.mustache`);
return fs.readFileSync(partialPath).toString();
}, {
escape: (value: string) => value,
});
}
4 changes: 4 additions & 0 deletions src/renderer/value-transformer/KotlinValueTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,8 @@ export class KotlinValueTransformer implements ValueTransformer {
convertTypeNameFromCustomMap(name: string): string {
return this.typeNameMap[name] ?? name;
}

null(): string {
return 'null';
}
}
4 changes: 4 additions & 0 deletions src/renderer/value-transformer/SwiftValueTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,8 @@ export class SwiftValueTransformer implements ValueTransformer {
convertTypeNameFromCustomMap(name: string): string {
return this.typeNameMap[name] ?? name;
}

null(): string {
return 'nil';
}
}
1 change: 1 addition & 0 deletions src/renderer/value-transformer/ValueTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export interface ValueTransformer {
convertValue(value: Value, type: ValueType): string;
convertEnumKey(text: string): string;
convertTypeNameFromCustomMap(name: string): string;
null(): string;
}
14 changes: 12 additions & 2 deletions src/renderer/views/MethodView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,23 @@ export class MethodView {
}

get parametersDeclaration(): string {
return this.parameters.map((parameter) => `${parameter.name}: ${parameter.type}`).join(', ');
return this.parameters.map((parameter) => {
let { defaultValue } = parameter;
if (defaultValue == null) {
return `${parameter.name}: ${parameter.type}`;
}
if (defaultValue === 'null') {
defaultValue = this.valueTransformer.null();
}
return `${parameter.name}: ${parameter.type} = ${defaultValue}`;
}).join(', ');
}

get parameters(): { name: string; type: string; last: boolean }[] {
get parameters(): { name: string; type: string; defaultValue?: string; last: boolean }[] {
return this.method.parameters.map((parameter, index) => ({
name: parameter.name,
type: this.valueTransformer.convertValueType(parameter.type),
defaultValue: parameter.defaultValue,
last: index === this.method.parameters.length - 1,
}));
}
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface Field {
type: ValueType;
staticValue?: Value;
documentation: string;
defaultValue?: string;
}

export type ValueType = NonEmptyType | OptionalType;
Expand Down

0 comments on commit 1303b05

Please sign in to comment.