Skip to content

Commit

Permalink
27 javadoc and fixes (#45)
Browse files Browse the repository at this point in the history
* Adding javadoc for interal classes
* Fix #43 #44
* Refine doc on SharedType
  • Loading branch information
cuzfrog authored Nov 5, 2024
1 parent 16dcbc7 commit f5e6bff
Show file tree
Hide file tree
Showing 77 changed files with 923 additions and 358 deletions.
27 changes: 15 additions & 12 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,18 @@ jobs:
with:
name: generated-sources
path: |
it/java17/target/generated-sources
./it/java8/target/generated-sources
./it/java17/target/generated-sources
if-no-files-found: error
retention-days: 3
- name: Upload jars
uses: actions/upload-artifact@v4
with:
name: jars
path: |
~/.m2/repository/org/sharedtype
if-no-files-found: error
retention-days: 3
- name: Remove jars from cache
run: rm -rf ~/.m2/repository/org/sharedtype

Expand Down Expand Up @@ -90,20 +93,20 @@ jobs:
- uses: actions/download-artifact@v4
with:
name: generated-sources
path: it/java17/target/generated-sources
- name: Display downloaded artifact
run: ls -lhR it/java17/target/generated-sources
path: ./it/
# - name: Display downloaded artifact
# run: ls -lhR ./it/
- name: Test Typescript
working-directory: client-test/typescript
run: |
npm i
npm run test
clean-artifact:
needs: [ jdk_compatibility_test, client_test ]
runs-on: ubuntu-latest
if: always()
steps:
- uses: geekyeggo/delete-artifact@v5
with:
name: dist
# clean-artifact:
# needs: [ jdk_compatibility_test, client_test ]
# runs-on: ubuntu-latest
# if: always()
# steps:
# - uses: geekyeggo/delete-artifact@v5
# with:
# name: dist
87 changes: 61 additions & 26 deletions annotation/src/main/java/org/sharedtype/annotation/SharedType.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,64 @@
import java.lang.annotation.Target;

/**
* <p>Share a type. <a href="https://github.com/cuzfrog/SharedType">Website</a></p>
* <p>Mark a class, record, enum, or interface for target code generation.</p>
*
* <p>
* <b>Annotation Processing:</b><br>
* This annotation is retained only in source code.
* That means it is not visible if source code is not directly participating in annotation processing.
* E.g. if it is in a dependency jar in a project with multi-module build.
* <br>
* <br>
* <b>Inner class:</b>
* When used together with <b>Lombok</b>, the processing order matters.
* If processed before Lombok, SharedType will see only the original source code.
* E.g. if getters are handled by Lombok @Getter, SharedType will not see the getter method.
* It's recommended to execute SharedType before Lombok, since Lombok does not provide extra info to SharedType.
* Also you may only want a fast execution of SharedType with "-proc:only" without other annotation processors.
* </p>
*
* <p>
* <b>Configurations:</b><br>
* Properties on class level (via this annotation) will take precedence over global properties.
* Properties that only apply to global level will not be present on class level.
* </p>
*
* <p>
* <b>Inner class:</b><br>
* Declared inner and nested types will not be included by default, unless they are referenced by other types.
* Non-static inner classes are not supported, see documentation for details.
* TODO: doc for nested types
* Non-static inner classes are not supported.
* </p>
*
* <p>
* <b>Generics:</b><br>
* Generics are supported. But it's also limited to target schema's capacity.
* </p>
*
* <p>
* <b>Collections:</b><br>
* Iterables and arrays are treated as arrays. Map is mapped to:
* <ul>
* <li>Typescript: {@code [key: string]: T} where {@code T} can be a reified type.</li>
* </ul>
* </p>
*
* <p><a href="https://github.com/cuzfrog/SharedType">SharedType Website</a></p></p>
*
* @author Cause Chung
* @implNote generics type bounds are not supported yet, Map is not supported yet.
*/
@Retention(RetentionPolicy.SOURCE)
@Target({java.lang.annotation.ElementType.TYPE})
@Documented
public @interface SharedType {
/**
* <p>
* The name of the emitted type. If not specified, the simple name of the annotated type will be used.
* This may be used to help avoid conflicting names in target output.
* The name of the emitted type. If not specified, the simple name of the annotated type will be used.
* This may be used to help avoid conflicting names in target code.
* </p>
* <br>
* <p>
* How possibly conflicting names are resolved:
* How conflicting names are resolved:
* <ul>
* <li>Typescript: simple name of a class is used as type name. Duplicate names are not allowed.</li>
* </ul>
Expand All @@ -38,36 +73,36 @@
String name() default "";

/**
* Includes fields, record components, accessors, or constants in a type.
* <p>
* To exclude a particular component, use {@link Ignore}.
* Configure whether to include fields, record components, accessors, or constants in a type.
* All included by default.
* </p>
* <br>
* <p>
* Fields and accessors duplicates resolution:
* <ul>
* <li>In classes, fields and accessors effectively with the same name will be merged.</li>
* <li>In records, when accessors are included, records components are ignored.</li>
* </ul>
* To exclude a particular component, use {@link Ignore}.
* Fields and accessors effectively with the same name will be merged.
* </p>
*
* @see ComponentType
* @see ComponentType#FIELDS
* @see ComponentType#ACCESSORS
* @see ComponentType#CONSTANTS
*/
ComponentType[] includes() default {ComponentType.FIELDS, ComponentType.ACCESSORS};
ComponentType[] includes() default {ComponentType.FIELDS, ComponentType.ACCESSORS, ComponentType.CONSTANTS};

/**
* Mark a method as an accessor regardless of its name. This annotation will be ignored if {@link #includes()} does not include {@link ComponentType#ACCESSORS}.
* Mark a method as an accessor regardless of its name.
* Getter prefixes are configured in global properties.
* This annotation will be ignored if {@link #includes()} does not include {@link ComponentType#ACCESSORS}.
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
@interface Accessor {
}

/**
* Exclude fields, record components, accessors in a type. Or ignore a dependent type, e.g. a supertype.
* Exclude fields, record components, accessors in a type, or a dependency type, e.g. a supertype.
* <p>
* <b>When placed on type:</b> a subtype of this type will not include inherited members from this type.
* But if this type is referenced directly as type of a field or return type of an accessor, an error will be reported,
* <b>When placed on a type:</b> a subtype of this type will not extend this type in target code.
* But if this type is referenced directly as type of a field or return type of an accessor, a compilation error will be reported,
* unless the field or accessor is also ignored.
* </p>
*/
Expand All @@ -78,15 +113,13 @@

/**
* Mark enum value. By default, enum value is the enum constant name. The enum value must be literals (e.g. 1, "a", true) in enum constant expressions.
* <br>
* <p>
* When placed on:
* <ul>
* <li>Constructor parameter - the literal value served to this parameter from enum constant expressions will be used.</li>
* <li>Field - the constructor parameter with the same name and type will be used as if constructor parameter is annotated.</li>
* </ul>
* </p>
* <br>
* <p>
* Below are some valid examples:
* </p>
Expand Down Expand Up @@ -134,10 +167,10 @@ enum ComponentType {
*/
FIELDS,
/**
* Represents 0 argument non-static methods:
* Represents 0 argument non-static methods that:
* <ul>
* <li>with name same as its instance field. Or fluent getter. This includes record's component accessor.</li>
* <li>starting with a getter prefix. By default, prefixes include 'get' or 'is', which can be configured via global properties.</li>
* <li>have names same as respective instance fields, aka, fluent getter. This includes record's component accessor.</li>
* <li>start with a getter prefix. By default, prefixes include 'get' or 'is', which can be configured via global properties.</li>
* <li>annotated with {@link Accessor}.</li>
* </ul>
*/
Expand All @@ -148,6 +181,8 @@ enum ComponentType {
* <li>Class/record static fields with static values.</li>
* </ul>
* Fields with values that cannot be resolved at compile time will not be included. A corresponding warning will be given.
*
* @implNote not implement yet.
*/
CONSTANTS,
}
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions client-test/typescript/src/index.java8.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type * from "../../../it/java8/target/generated-sources/types.d.ts";
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {DependencyClassA, DependencyClassB, DependencyClassC, EnumGalaxy, EnumSize, EnumTShirt, JavaRecord, AnotherJavaClass} from "../src/index.js";
import type {DependencyClassA, DependencyClassB, DependencyClassC, EnumGalaxy, EnumSize, EnumTShirt, JavaRecord, AnotherJavaClass} from "../src/index.java17.js";

export const list1: EnumGalaxy[] = ["Andromeda", "MilkyWay", "Triangulum"];
export const record1: Record<EnumTShirt, number> = {
Expand All @@ -16,7 +16,9 @@ export const dependencyClassB: DependencyClassB = {

export const dependencyClassA: DependencyClassA = {
a: 0,
b: dependencyClassB
b: dependencyClassB,
notIgnoredImplementedMethod: 0,
value: 0,
};
dependencyClassC.a = dependencyClassA

Expand Down Expand Up @@ -50,6 +52,7 @@ export const obj: Omit<JavaRecord<string, number>, "aVoid" | "genericMap"> = {
primitiveLong: 0,
primitiveShort: 0,
string: "",
value: "",
};

export const anotherJavaClass: AnotherJavaClass = {
Expand Down
9 changes: 9 additions & 0 deletions client-test/typescript/tests/types.java8.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { JavaClass } from "../src/index.java8.d.ts";

export const javaClass: JavaClass = {
string: "",
size: 1,
notIgnoredImplementedMethod: 0,
a: 0,
value: 0
};
1 change: 1 addition & 0 deletions doc/Development.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ Then attach your debugger on it.
1. since annotation processing is one shot execution, JIT is not likely to optimize the code. So prefer plain loop than long calling stacks like Stream chains.
2. no adding dependencies without strong justification.
3. Lombok is used in this project, but do not abuse. Only use it to replace unavoidable boilerplate code, and not to increase the bytecode size.
Do not use compile time heavy annotation like `lombok.val`.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* @see ArrayTypeInfo
* @author Cause Chung
*/
@EqualsAndHashCode(of = "qualifiedName")
@EqualsAndHashCode(of = {"qualifiedName", "typeArgs"})
@Builder
public final class ConcreteTypeInfo implements TypeInfo {
private final String qualifiedName;
Expand Down
12 changes: 6 additions & 6 deletions internal/src/main/java/org/sharedtype/domain/TypeInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
/**
* Type information.
*
* @see TypeDef
* @author Cause Chung
* @see TypeDef
*/
public interface TypeInfo extends Serializable {
/**
* <p>Check if this type and its dependency types are resolved.</p>
* <p>
* When parsing a type's structure, a dependency type is firstly captured as a {@link TypeInfo}.
* At this stage, because we don't know its output structure or if it needs output at all, we mark it as unresolved.
* Also due to possible cyclic dependencies, the resolution stage needs to be performed after initial parsing state.
* During resolution, once a type is parsed, it's marked as resolved.
* Note that a type is marked as resolved when created, if it can be determined at that time.
* When parsing a type's structure, a dependency type is firstly captured as a {@link TypeInfo}.
* At this stage, because we don't know its output structure or if it needs output at all, we mark it as unresolved.
* Also due to possible cyclic dependencies, the resolution stage needs to be performed after initial parsing state.
* During resolution, once a type is parsed, it's marked as resolved.
* Note that a type is marked as resolved when created, if it can be determined at that time.
* </p>
* <p>Object contains resolved flag as a mutable state</p>
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@

import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;

/**
* Represents a generic type variable.
* <br>
* A type variable refers to a generic type parameter, it has a notation like "T" or bound information like "T extends Number".
* A type argument is the actual type of the type variable. E.g. {@code "Integer" in "List<Integer>"}.
*
* @see ConcreteTypeInfo#typeArgs()
* @author Cause Chung
*/
@Getter
@EqualsAndHashCode
@Builder
public final class TypeVariableInfo implements TypeInfo {
private final String name;
// TODO: support generic bounds

public String name() {
return name;
}

@Override
public boolean resolved() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package org.sharedtype.processor.support;
package org.sharedtype.support;

import org.sharedtype.processor.support.exception.SharedTypeInternalError;
import org.sharedtype.support.exception.SharedTypeInternalError;

import java.util.Collection;

/**
*
* @author Cause Chung
*/
// TODO: remove varargs to improve performance
public final class Preconditions {
private Preconditions() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.sharedtype.support.annotation;


import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* Mark an issue number.
*
* @author Cause Chung
*/
@Retention(RetentionPolicy.SOURCE)
public @interface Issue {
int value();
String comment() default "";
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sharedtype.processor.support.annotation;
package org.sharedtype.support.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
Expand All @@ -7,6 +7,8 @@

/**
* Indicate side effect performed by a method or on a parameter.
*
* @author Cause Chung
*/
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.SOURCE)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package org.sharedtype.processor.support.annotation;
package org.sharedtype.support.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Indicate that the visibility of a method or class is greater than needed in compile scope code, but exposed for testing purpose.
*
* @author Cause Chung
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.SOURCE)
public @interface VisibleForTesting {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package org.sharedtype.processor.support.exception;
package org.sharedtype.support.exception;

/**
* Indicate an exception, equivalent to {@link RuntimeException}.
*
* @author Cause Chung
*/
public final class SharedTypeException extends RuntimeException {
public SharedTypeException(String message) {
super(message);
Expand Down
Loading

0 comments on commit f5e6bff

Please sign in to comment.