Skip to content

Commit

Permalink
use branded types for enums
Browse files Browse the repository at this point in the history
  • Loading branch information
vegegoku committed Mar 10, 2024
1 parent c75732d commit d67c3da
Show file tree
Hide file tree
Showing 16 changed files with 393 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,9 @@ public void testMethodsLinks() throws IOException {
public void testIssue99() throws IOException {
testDocs("links.issue99");
}

@Test
public void brandedTypes() throws IOException {
testDocs("branded");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright © 2023 Vertispan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vertispan.tsdefs.tests.tsdocs.doclet.branded;

import jsinterop.annotations.JsType;

/** Branded types enum test */
@JsType
public enum Direction {
LEFT,
RIGHT,
UP,
DOWN
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class Formatting {
public static final String NONE = "";

public static final String NEW_LINE = "\n";
public static final String CR = "\r";
public static final String SPACE = " ";
public static final String END_LINE = ";";
public static final String COMMA = ", ";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,10 @@ public boolean isClass() {
return element.getKind().isClass() && !isTsInterface();
}

public boolean isEnum() {
return ElementKind.ENUM == element.getKind();
}

public boolean isMethod() {
return ElementKind.METHOD.equals(element.getKind());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright © 2023 Vertispan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vertispan.tsdefs.impl.model;

import static com.vertispan.tsdefs.impl.Formatting.NEW_LINE;

public class TsBrand {
private final String name;
private final String namespace;
private final TsType type;

public TsBrand(String name, String namespace) {
this.name = name;
this.namespace = namespace;
this.type = new TsType(name + "Type", namespace);
}

public String emit(String indent) {
StringBuffer sb = new StringBuffer();
sb.append(indent);
sb.append("const " + name + "__brand: unique symbol");
sb.append(NEW_LINE);
sb.append(indent);
sb.append("type Brand<B> = { [" + name + "__brand]: B }");
sb.append(NEW_LINE);
sb.append(indent);
sb.append("export type Branded<T, B> = T & Brand<B>");
sb.append(NEW_LINE);
sb.append(indent);
sb.append("type " + name + "Type = Branded<string, \"" + name + "\">;");
sb.append(NEW_LINE);
sb.append(indent);
return sb.toString();
}

public TsType getType() {
return this.type;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright © 2023 Vertispan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vertispan.tsdefs.impl.model;

import static com.vertispan.tsdefs.impl.Formatting.NEW_LINE;

import com.vertispan.tsdefs.impl.builders.HasDocs;
import com.vertispan.tsdefs.impl.builders.HasFunctions;
import com.vertispan.tsdefs.impl.builders.HasNamespace;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;

public class TsBrandedType implements HasNamespace {
private final String name;
private final String namespace;
private TsType type;
private final Set<TsModifier> modifiers = new LinkedHashSet<>();
private final Set<String> enumerations = new LinkedHashSet<>();
private final Set<TsMethod> functions = new LinkedHashSet<>();
private TsDoc tsDoc;
private boolean deprecated;

private TsBrandedType(String name, String namespace, TsType type) {
this.name = name;
this.namespace = namespace;
this.type = type;
}

public static TsBrandedType.TsBrandedTypeBuilder builder(
String name, String namespace, TsType type) {
return new TsBrandedType.TsBrandedTypeBuilder(name, namespace, type);
}

public String getName() {
return name;
}

public String getNamespace() {
return namespace;
}

public TsType getType() {
return type;
}

public String emit(String indent, String parentNamespace) {
StringBuffer sb = new StringBuffer();

TsBrand tsBrand = new TsBrand(name, namespace);
sb.append(tsBrand.emit(indent));
sb.append(NEW_LINE);

TsClass.TsClassBuilder classBuilder =
TsClass.builder(name, namespace).addModifiers(TsModifier.EXPORT).setDocs(tsDoc);
enumerations.stream()
.map(
enumeration ->
TsProperty.builder(enumeration, tsBrand.getType())
.setDocs(TsDoc.empty())
.addModifiers(TsModifier.STATIC, TsModifier.READONLY)
.build())
.forEach(classBuilder::addProperty);

functions.forEach(classBuilder::addFunction);

sb.append(classBuilder.build().emit(indent, parentNamespace));

return sb.toString();
}

public static class TsBrandedTypeBuilder
implements HasDocs<TsBrandedType.TsBrandedTypeBuilder>,
HasFunctions<TsBrandedType.TsBrandedTypeBuilder> {
private final TsBrandedType tsEnum;

private TsBrandedTypeBuilder(String name, String namespace, TsType type) {
this.tsEnum = new TsBrandedType(name, namespace, type);
}

public TsBrandedType.TsBrandedTypeBuilder addEnumeration(String name) {
this.tsEnum.enumerations.add(name);
return this;
}

public TsBrandedType.TsBrandedTypeBuilder addModifiers(TsModifier... modifiers) {
this.tsEnum.modifiers.addAll(Arrays.asList(modifiers));
return this;
}

@Override
public TsBrandedType.TsBrandedTypeBuilder setDocs(TsDoc tsDoc) {
this.tsEnum.tsDoc = tsDoc;
return this;
}

public TsBrandedType.TsBrandedTypeBuilder setDeprecated(boolean deprecated) {
this.tsEnum.deprecated = deprecated;
return this;
}

@Override
public TsBrandedType.TsBrandedTypeBuilder addFunction(TsMethod function) {
this.tsEnum.functions.add(function);
return this;
}

public TsBrandedType build() {
return this.tsEnum;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public class TsNamespace {
private List<TsInterface> tsInterfaces = new ArrayList<>();
private List<TsFunction> tsFunctions = new ArrayList<>();
private List<TsClass> tsClasses = new ArrayList<>();
private List<TsEnum> tsEnums = new ArrayList<>();
private List<TsTypeDef> tsTypeDefs = new ArrayList<>();
private List<TsBrandedType> tsBrandedTypes = new ArrayList<>();

public TsNamespace(String namespace) {
this.namespace = namespace;
Expand All @@ -52,14 +53,19 @@ public void addFunction(TsFunction tsFunction) {
this.tsFunctions.add(tsFunction);
}

public void addTsEnum(TsEnum tsEnum) {
this.tsEnums.add(tsEnum);
public void addTsTypeDef(TsTypeDef tsTypeDef) {
this.tsTypeDefs.add(tsTypeDef);
}

public void addBrandedType(TsBrandedType tsBrandedType) {
this.tsBrandedTypes.add(tsBrandedType);
}

public boolean isEmpty() {
return tsInterfaces.isEmpty()
&& tsFunctions.isEmpty()
&& tsEnums.isEmpty()
&& tsTypeDefs.isEmpty()
&& tsBrandedTypes.isEmpty()
&& (tsClasses.isEmpty() || tsClasses.stream().allMatch(TsClass::isEmpty));
}

Expand Down Expand Up @@ -96,9 +102,16 @@ public String emit(String indent, String parentNamespace) {
.collect(Collectors.joining(NEW_LINE, optionalln(tsClasses), optionalln(tsClasses))));

sb.append(
tsEnums.stream()
.map(tsEnum -> tsEnum.emit(indent + INDENT, namespace))
.collect(Collectors.joining(NEW_LINE, optionalln(tsEnums), optionalln(tsEnums))));
tsTypeDefs.stream()
.map(tsTypeDef -> tsTypeDef.emit(indent + INDENT, namespace))
.collect(Collectors.joining(NEW_LINE, optionalln(tsTypeDefs), optionalln(tsTypeDefs))));

sb.append(
tsBrandedTypes.stream()
.map(tsTypeDef -> tsTypeDef.emit(indent + INDENT, namespace))
.collect(
Collectors.joining(
NEW_LINE, optionalln(tsBrandedTypes), optionalln(tsBrandedTypes))));

sb.append("}").append(NEW_LINE);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import java.util.LinkedHashSet;
import java.util.Set;

public class TsEnum implements HasNamespace {
public class TsTypeDef implements HasNamespace {
private final String name;
private final String namespace;
private TsCustomType type;
Expand All @@ -35,7 +35,7 @@ public class TsEnum implements HasNamespace {
private TsDoc tsDoc;
private boolean deprecated;

private TsEnum(String name, String namespace, TsCustomType type) {
private TsTypeDef(String name, String namespace, TsCustomType type) {
this.name = name;
this.namespace = namespace;
this.type = type;
Expand Down Expand Up @@ -84,41 +84,41 @@ public String emit(String indent, String parentNamespace) {
}

public static class TsEnumBuilder implements HasDocs<TsEnumBuilder>, HasFunctions<TsEnumBuilder> {
private final TsEnum tsEnum;
private final TsTypeDef tsTypeDef;

private TsEnumBuilder(String name, String namespace, TsCustomType type) {
this.tsEnum = new TsEnum(name, namespace, type);
this.tsTypeDef = new TsTypeDef(name, namespace, type);
}

public TsEnumBuilder addEnumeration(String name) {
this.tsEnum.enumerations.add(name);
this.tsTypeDef.enumerations.add(name);
return this;
}

public TsEnumBuilder addModifiers(TsModifier... modifiers) {
this.tsEnum.modifiers.addAll(Arrays.asList(modifiers));
this.tsTypeDef.modifiers.addAll(Arrays.asList(modifiers));
return this;
}

@Override
public TsEnumBuilder setDocs(TsDoc tsDoc) {
this.tsEnum.tsDoc = tsDoc;
this.tsTypeDef.tsDoc = tsDoc;
return this;
}

public TsEnumBuilder setDeprecated(boolean deprecated) {
this.tsEnum.deprecated = deprecated;
this.tsTypeDef.deprecated = deprecated;
return this;
}

@Override
public TsEnumBuilder addFunction(TsMethod function) {
this.tsEnum.functions.add(function);
this.tsTypeDef.functions.add(function);
return this;
}

public TsEnum build() {
return this.tsEnum;
public TsTypeDef build() {
return this.tsTypeDef;
}
}
}
Loading

0 comments on commit d67c3da

Please sign in to comment.