Skip to content

Commit ee434aa

Browse files
authored
Merge pull request #1259 from appwrite/fix-java-examples-kotlin-syntax
2 parents 05367bc + 9902d29 commit ee434aa

File tree

20 files changed

+324
-125
lines changed

20 files changed

+324
-125
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ jobs:
9494
- name: Setup PHP with PECL extension
9595
uses: shivammathur/setup-php@v2
9696
with:
97-
php-version: ${{ matrix.php-version }}
97+
php-version: '8.3'
9898
extensions: curl
9999

100100
- name: Install

composer.lock

Lines changed: 82 additions & 68 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/SDK/Language.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@ abstract public function getParamDefault(array $param): string;
7070

7171
/**
7272
* @param array $param
73+
* @param string $lang Optional language variant (for multi-language SDKs)
7374
* @return string
7475
*/
75-
abstract public function getParamExample(array $param): string;
76+
abstract public function getParamExample(array $param, string $lang = ''): string;
7677

7778
/**
7879
* @param string $key

src/SDK/Language/CLI.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,10 @@ public function getTypeName(array $parameter, array $spec = []): string
377377

378378
/**
379379
* @param array $param
380+
* @param string $lang
380381
* @return string
381382
*/
382-
public function getParamExample(array $param): string
383+
public function getParamExample(array $param, string $lang = ''): string
383384
{
384385
$type = $param['type'] ?? '';
385386
$example = $param['example'] ?? '';

src/SDK/Language/Dart.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,10 @@ public function getParamDefault(array $param): string
234234

235235
/**
236236
* @param array $param
237+
* @param string $lang
237238
* @return string
238239
*/
239-
public function getParamExample(array $param): string
240+
public function getParamExample(array $param, string $lang = ''): string
240241
{
241242
$type = $param['type'] ?? '';
242243
$example = $param['example'] ?? '';

src/SDK/Language/Deno.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,10 @@ public function getTypeName(array $parameter, array $spec = []): string
181181

182182
/**
183183
* @param array $param
184+
* @param string $lang
184185
* @return string
185186
*/
186-
public function getParamExample(array $param): string
187+
public function getParamExample(array $param, string $lang = ''): string
187188
{
188189
$type = $param['type'] ?? '';
189190
$example = $param['example'] ?? '';

src/SDK/Language/DotNet.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,10 @@ public function getParamDefault(array $param): string
261261

262262
/**
263263
* @param array $param
264+
* @param string $lang
264265
* @return string
265266
*/
266-
public function getParamExample(array $param): string
267+
public function getParamExample(array $param, string $lang = ''): string
267268
{
268269
$type = $param['type'] ?? '';
269270
$example = $param['example'] ?? '';

src/SDK/Language/Go.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,10 @@ public function getParamDefault(array $param): string
238238

239239
/**
240240
* @param array $param
241+
* @param string $lang
241242
* @return string
242243
*/
243-
public function getParamExample(array $param): string
244+
public function getParamExample(array $param, string $lang = ''): string
244245
{
245246
$type = $param['type'] ?? '';
246247
$example = $param['example'] ?? '';

src/SDK/Language/GraphQL.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,10 @@ public function getParamDefault(array $param): string
128128

129129
/**
130130
* @param array $param
131+
* @param string $lang
131132
* @return string
132133
*/
133-
public function getParamExample(array $param): string
134+
public function getParamExample(array $param, string $lang = ''): string
134135
{
135136
$type = $param['type'] ?? '';
136137
$example = $param['example'] ?? '';

src/SDK/Language/Kotlin.php

Lines changed: 201 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,10 @@ public function getParamDefault(array $param): string
205205

206206
/**
207207
* @param array $param
208+
* @param string $lang Language variant: 'kotlin' (default) or 'java'
208209
* @return string
209210
*/
210-
public function getParamExample(array $param): string
211+
public function getParamExample(array $param, string $lang = 'kotlin'): string
211212
{
212213
$type = $param['type'] ?? '';
213214
$example = $param['example'] ?? '';
@@ -230,40 +231,28 @@ public function getParamExample(array $param): string
230231
$output .= "\"\"";
231232
break;
232233
case self::TYPE_OBJECT:
233-
$output .= 'mapOf( "a" to "b" )';
234+
$output .= $lang === 'java'
235+
? 'Map.of("a", "b")'
236+
: 'mapOf( "a" to "b" )';
234237
break;
235238
case self::TYPE_ARRAY:
236-
$output .= 'listOf()';
239+
$output .= $lang === 'java' ? 'List.of()' : 'listOf()';
237240
break;
238241
}
239242
} else {
240243
switch ($type) {
241244
case self::TYPE_OBJECT:
242245
$decoded = json_decode($example, true);
243246
if ($decoded && is_array($decoded)) {
244-
$mapEntries = [];
245-
foreach ($decoded as $key => $value) {
246-
$formattedKey = '"' . $key . '"';
247-
if (is_string($value)) {
248-
$formattedValue = '"' . $value . '"';
249-
} elseif (is_bool($value)) {
250-
$formattedValue = $value ? 'true' : 'false';
251-
} elseif (is_null($value)) {
252-
$formattedValue = 'null';
253-
} elseif (is_array($value)) {
254-
$formattedValue = 'listOf()'; // Simplified for nested arrays
255-
} else {
256-
$formattedValue = (string)$value;
257-
}
258-
$mapEntries[] = ' ' . $formattedKey . ' to ' . $formattedValue;
259-
}
260-
if (count($mapEntries) > 0) {
261-
$output .= "mapOf(\n" . implode(",\n", $mapEntries) . "\n )";
247+
if ($lang === 'java') {
248+
$output .= $this->getJavaMapExample($decoded);
262249
} else {
263-
$output .= 'mapOf( "a" to "b" )';
250+
$output .= $this->getKotlinMapExample($decoded);
264251
}
265252
} else {
266-
$output .= 'mapOf( "a" to "b" )';
253+
$output .= $lang === 'java'
254+
? 'Map.of("a", "b")'
255+
: 'mapOf( "a" to "b" )';
267256
}
268257
break;
269258
case self::TYPE_FILE:
@@ -273,15 +262,9 @@ public function getParamExample(array $param): string
273262
break;
274263
case self::TYPE_ARRAY:
275264
if ($this->isPermissionString($example)) {
276-
$output .= $this->getPermissionExample($example);
265+
$output .= $this->getPermissionExample($example, $lang);
277266
} else {
278-
if (\str_starts_with($example, '[')) {
279-
$example = \substr($example, 1);
280-
}
281-
if (\str_ends_with($example, ']')) {
282-
$example = \substr($example, 0, -1);
283-
}
284-
$output .= 'listOf(' . $example . ')';
267+
$output .= $this->getArrayExample($example, $lang);
285268
}
286269
break;
287270
case self::TYPE_BOOLEAN:
@@ -296,6 +279,190 @@ public function getParamExample(array $param): string
296279
return $output;
297280
}
298281

282+
/**
283+
* Generate Kotlin-style map initialization
284+
*
285+
* @param array $data
286+
* @param int $indentLevel Indentation level for nested maps
287+
* @return string
288+
*/
289+
protected function getKotlinMapExample(array $data, int $indentLevel = 0): string
290+
{
291+
$mapEntries = [];
292+
$baseIndent = str_repeat(' ', $indentLevel + 2);
293+
294+
foreach ($data as $key => $value) {
295+
$formattedKey = '"' . $key . '"';
296+
if (is_string($value)) {
297+
$formattedValue = '"' . $value . '"';
298+
} elseif (is_bool($value)) {
299+
$formattedValue = $value ? 'true' : 'false';
300+
} elseif (is_null($value)) {
301+
$formattedValue = 'null';
302+
} elseif (is_array($value)) {
303+
// Check if it's an associative array (object) or indexed array
304+
$isObject = !array_is_list($value);
305+
if ($isObject) {
306+
$formattedValue = $this->getKotlinMapExample($value, $indentLevel + 1);
307+
} else {
308+
$formattedValue = $this->getArrayExample(json_encode($value), 'kotlin');
309+
}
310+
} else {
311+
$formattedValue = (string)$value;
312+
}
313+
$mapEntries[] = $baseIndent . $formattedKey . ' to ' . $formattedValue;
314+
}
315+
316+
if (count($mapEntries) > 0) {
317+
$closeIndent = str_repeat(' ', $indentLevel + 1);
318+
return "mapOf(\n" . implode(",\n", $mapEntries) . "\n" . $closeIndent . ")";
319+
} else {
320+
return 'mapOf( "a" to "b" )';
321+
}
322+
}
323+
324+
/**
325+
* Generate Java-style map initialization using Map.of()
326+
*
327+
* @param array $data
328+
* @param int $indentLevel Indentation level for nested maps
329+
* @return string
330+
*/
331+
protected function getJavaMapExample(array $data, int $indentLevel = 0): string
332+
{
333+
$mapEntries = [];
334+
$baseIndent = str_repeat(' ', $indentLevel + 2);
335+
336+
foreach ($data as $key => $value) {
337+
$formattedKey = '"' . $key . '"';
338+
if (is_string($value)) {
339+
$formattedValue = '"' . $value . '"';
340+
} elseif (is_bool($value)) {
341+
$formattedValue = $value ? 'true' : 'false';
342+
} elseif (is_null($value)) {
343+
$formattedValue = 'null';
344+
} elseif (is_array($value)) {
345+
// Check if it's an associative array (object) or indexed array
346+
$isObject = !array_is_list($value);
347+
if ($isObject) {
348+
$formattedValue = $this->getJavaMapExample($value, $indentLevel + 1);
349+
} else {
350+
$formattedValue = $this->getArrayExample(json_encode($value), 'java');
351+
}
352+
} else {
353+
$formattedValue = (string)$value;
354+
}
355+
$mapEntries[] = $baseIndent . $formattedKey . ', ' . $formattedValue;
356+
}
357+
358+
if (count($mapEntries) > 0) {
359+
$closeIndent = str_repeat(' ', $indentLevel + 1);
360+
return "Map.of(\n" . implode(",\n", $mapEntries) . "\n" . $closeIndent . ")";
361+
} else {
362+
return 'Map.of("a", "b")';
363+
}
364+
}
365+
366+
/**
367+
* Generate array example for the given language
368+
*
369+
* @param string $example Array example like '[1, 2, 3]' or '[{"key": "value"}]'
370+
* @param string $lang Language variant: 'kotlin' or 'java'
371+
* @return string
372+
*/
373+
protected function getArrayExample(string $example, string $lang = 'kotlin'): string
374+
{
375+
// Try to decode as JSON to handle arrays of objects
376+
$decoded = json_decode($example, true);
377+
if ($decoded && is_array($decoded)) {
378+
$arrayItems = [];
379+
foreach ($decoded as $item) {
380+
if (is_array($item)) {
381+
// Check if it's an associative array (object) or indexed array (nested array)
382+
$isObject = !array_is_list($item);
383+
384+
if ($isObject) {
385+
// It's an object/map, convert it
386+
if ($lang === 'java') {
387+
$arrayItems[] = $this->getJavaMapExample($item);
388+
} else {
389+
$arrayItems[] = $this->getKotlinMapExample($item);
390+
}
391+
} else {
392+
// It's a nested array, recursively convert it
393+
$arrayItems[] = $this->getArrayExample(json_encode($item), $lang);
394+
}
395+
} else {
396+
// Primitive value
397+
if (is_string($item)) {
398+
$arrayItems[] = '"' . $item . '"';
399+
} elseif (is_bool($item)) {
400+
$arrayItems[] = $item ? 'true' : 'false';
401+
} elseif (is_null($item)) {
402+
$arrayItems[] = 'null';
403+
} else {
404+
$arrayItems[] = (string)$item;
405+
}
406+
}
407+
}
408+
return $lang === 'java'
409+
? 'List.of(' . implode(', ', $arrayItems) . ')'
410+
: 'listOf(' . implode(', ', $arrayItems) . ')';
411+
}
412+
413+
// Fallback to old behavior for non-JSON arrays
414+
if (\str_starts_with($example, '[')) {
415+
$example = \substr($example, 1);
416+
}
417+
if (\str_ends_with($example, ']')) {
418+
$example = \substr($example, 0, -1);
419+
}
420+
return $lang === 'java'
421+
? 'List.of(' . $example . ')'
422+
: 'listOf(' . $example . ')';
423+
}
424+
425+
/**
426+
* Generate permission example for the given language
427+
*
428+
* @param string $example Permission string like '["read(\"any\")"]'
429+
* @param string $lang Language variant: 'kotlin' or 'java'
430+
* @return string
431+
*/
432+
public function getPermissionExample(string $example, string $lang = 'kotlin'): string
433+
{
434+
$permissions = [];
435+
$staticOp = $this->getStaticAccessOperator();
436+
$quote = $this->getStringQuote();
437+
$prefix = $this->getPermissionPrefix();
438+
439+
foreach ($this->extractPermissionParts($example) as $permission) {
440+
$args = [];
441+
if ($permission['id'] !== null) {
442+
$args[] = $quote . $permission['id'] . $quote;
443+
}
444+
if ($permission['innerRole'] !== null) {
445+
$args[] = $quote . $permission['innerRole'] . $quote;
446+
}
447+
$argsString = implode(', ', $args);
448+
449+
$action = $permission['action'];
450+
$role = $permission['role'];
451+
$action = $this->transformPermissionAction($action);
452+
$role = $this->transformPermissionRole($role);
453+
454+
$permissions[] = $prefix . 'Permission' . $staticOp . $action . '(' . $prefix . 'Role' . $staticOp . $role . '(' . $argsString . '))';
455+
}
456+
457+
$permissionsString = implode(', ', $permissions);
458+
459+
// For Java, use List.of() instead of listOf()
460+
if ($lang === 'java') {
461+
return 'List.of(' . $permissionsString . ')';
462+
}
463+
return 'listOf(' . $permissionsString . ')';
464+
}
465+
299466
/**
300467
* @return array
301468
*/
@@ -496,6 +663,9 @@ public function getFilters(): array
496663
new TwigFilter('propertyAssignment', function (array $property, array $spec) {
497664
return $this->getPropertyAssignment($property, $spec);
498665
}),
666+
new TwigFilter('javaParamExample', function (array $param) {
667+
return $this->getParamExample($param, 'java');
668+
}, ['is_safe' => ['html']]),
499669
];
500670
}
501671

0 commit comments

Comments
 (0)