From 6eae80d6eb9dc09a8b68b208a8732a7e964639fb Mon Sep 17 00:00:00 2001 From: "Ahmad K. Bawaneh" Date: Wed, 24 Apr 2024 15:05:13 +0300 Subject: [PATCH] Emit consistent jsdocs for inherited members Mark method as deprecated if recursively it overrides a deprecated method, and adds inheritDoc tag if the overriding method does not provide its own documentation. fix #106 --- .../tsdefs/doclet/TsDocTreeVisitor.java | 5 +++ .../com/vertispan/tsdefs/doclet/TsDoclet.java | 12 ++++- .../tests/tsdocs/doclet/DocletTest.java | 5 +++ .../doclet/links/issue106/ChildJsType.java | 45 +++++++++++++++++++ .../doclet/links/issue106/SuperInterface.java | 25 +++++++++++ .../doclet/links/issue106/SuperJsType.java | 33 ++++++++++++++ .../tsdefs/impl/builders/TsElement.java | 41 ++++++++++++++++- .../vertispan/tsdefs/impl/model/TsDoc.java | 4 ++ 8 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/ChildJsType.java create mode 100644 jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/SuperInterface.java create mode 100644 jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/SuperJsType.java diff --git a/jsinterop-ts-defs-doclet/src/main/java/com/vertispan/tsdefs/doclet/TsDocTreeVisitor.java b/jsinterop-ts-defs-doclet/src/main/java/com/vertispan/tsdefs/doclet/TsDocTreeVisitor.java index 0bd80c7..4d20547 100644 --- a/jsinterop-ts-defs-doclet/src/main/java/com/vertispan/tsdefs/doclet/TsDocTreeVisitor.java +++ b/jsinterop-ts-defs-doclet/src/main/java/com/vertispan/tsdefs/doclet/TsDocTreeVisitor.java @@ -171,4 +171,9 @@ public String visitParam(ParamTree node, Element element) { .map(docTree -> docTree.accept(this, element)) .collect(Collectors.joining()); } + + @Override + public String visitInheritDoc(InheritDocTree node, Element element) { + return "@inheritDoc"; + } } diff --git a/jsinterop-ts-defs-doclet/src/main/java/com/vertispan/tsdefs/doclet/TsDoclet.java b/jsinterop-ts-defs-doclet/src/main/java/com/vertispan/tsdefs/doclet/TsDoclet.java index 90d31cb..4e6c7a0 100644 --- a/jsinterop-ts-defs-doclet/src/main/java/com/vertispan/tsdefs/doclet/TsDoclet.java +++ b/jsinterop-ts-defs-doclet/src/main/java/com/vertispan/tsdefs/doclet/TsDoclet.java @@ -24,6 +24,7 @@ import com.vertispan.tsdefs.impl.Formatting; import com.vertispan.tsdefs.impl.HasProcessorEnv; import com.vertispan.tsdefs.impl.LogWrapper; +import com.vertispan.tsdefs.impl.builders.TsElement; import com.vertispan.tsdefs.impl.model.TsDoc; import com.vertispan.tsdefs.impl.model.TypeScriptModule; import com.vertispan.tsdefs.impl.visitors.TypeVisitor; @@ -212,9 +213,18 @@ public TsDoc getDocs(Element element) { Optional.ofNullable(path).map(treePath -> env.getDocTrees().getDocCommentTree(path)); return docCommentTree .map(doctree -> TsDoc.of(doctree.accept(new TsDocTreeVisitor(this, this.env), element))) - .orElse(TsDoc.empty()); + .orElse(inheritedDocsOrEmpty(element)); } } + return inheritedDocsOrEmpty(element); + } + + private TsDoc inheritedDocsOrEmpty(Element element) { + + TsElement tsElement = TsElement.of(element, this); + if (tsElement.overridesAnyMethod()) { + return TsDoc.inherited(); + } return TsDoc.empty(); } diff --git a/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/DocletTest.java b/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/DocletTest.java index c71570e..2a62ed4 100644 --- a/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/DocletTest.java +++ b/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/DocletTest.java @@ -72,4 +72,9 @@ public void testMethodsLinks() throws IOException { public void testIssue99() throws IOException { testDocs("links.issue99"); } + + @Test + public void testIssue106() throws IOException { + testDocs("links.issue106"); + } } diff --git a/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/ChildJsType.java b/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/ChildJsType.java new file mode 100644 index 0000000..322bd0e --- /dev/null +++ b/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/ChildJsType.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2024 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.links.issue106; + +import jsinterop.annotations.JsType; + +@JsType +public class ChildJsType extends SuperJsType implements SuperInterface { + /** This method is documented in the child */ + @Override + public void doSomething() {} + + /** This method is documented in the child and inherits the parent docs. {@inheritDoc} */ + @Override + public void doSomethingElse() {} + + @Override + public void doSomethingDifferent() { + super.doSomethingDifferent(); + } + + @Override + public void deprecatedDoSomething() { + super.deprecatedDoSomething(); + } + + @Override + public void doFoo() {} + + @Override + public void doBarDeprecated() {} +} diff --git a/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/SuperInterface.java b/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/SuperInterface.java new file mode 100644 index 0000000..18f6f0c --- /dev/null +++ b/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/SuperInterface.java @@ -0,0 +1,25 @@ +/* + * Copyright © 2024 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.links.issue106; + +public interface SuperInterface { + + /** This is documented in the super interface */ + void doFoo(); + + @Deprecated + void doBarDeprecated(); +} diff --git a/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/SuperJsType.java b/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/SuperJsType.java new file mode 100644 index 0000000..c3d1cd9 --- /dev/null +++ b/jsinterop-ts-defs-doclet/src/test/java/com/vertispan/tsdefs/tests/tsdocs/doclet/links/issue106/SuperJsType.java @@ -0,0 +1,33 @@ +/* + * Copyright © 2024 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.links.issue106; + +import jsinterop.annotations.JsType; + +@JsType +public class SuperJsType { + + public void doSomething() {} + + /** This is the super type documentation */ + public void doSomethingElse() {} + + /** This is documented in the super type */ + public void doSomethingDifferent() {} + + @Deprecated + public void deprecatedDoSomething() {} +} diff --git a/jsinterop-ts-defs-impl/src/main/java/com/vertispan/tsdefs/impl/builders/TsElement.java b/jsinterop-ts-defs-impl/src/main/java/com/vertispan/tsdefs/impl/builders/TsElement.java index 8969e92..8cedacd 100644 --- a/jsinterop-ts-defs-impl/src/main/java/com/vertispan/tsdefs/impl/builders/TsElement.java +++ b/jsinterop-ts-defs-impl/src/main/java/com/vertispan/tsdefs/impl/builders/TsElement.java @@ -114,7 +114,7 @@ public boolean isInheritedGetter() { private boolean matchGetterPattern() { ExecutableElement executableElement = (ExecutableElement) element; return !isVoidType(executableElement.getReturnType(), env) - && executableElement.getParameters().size() == 0; + && executableElement.getParameters().isEmpty(); } public boolean isSetter() { @@ -456,6 +456,24 @@ public boolean override(ExecutableElement method) { env.elements().overrides(method, elementMethod, (TypeElement) element)); } + public boolean matchingAnySuperMethod( + ExecutableElement method, BiPredicate predicate) { + TsElement tsElement = TsElement.of(method.getEnclosingElement(), env); + return Stream.concat( + tsElement.allMethodsAndSuperClassesMethods().stream(), + tsElement.allSuperInterfacesMethods().stream()) + .anyMatch(elementMethod -> predicate.test(method, elementMethod)); + } + + public boolean overridesAnyMethod() { + return this.isMethod() + && matchingAnySuperMethod( + (ExecutableElement) this.element, + (method, superMethod) -> + env.elements() + .overrides(method, superMethod, (TypeElement) element.getEnclosingElement())); + } + public Optional superElement() { TypeMirror superclass = ((TypeElement) element).getSuperclass(); if (nonNull(superclass) && !superclass.getKind().equals(TypeKind.NONE)) { @@ -695,9 +713,26 @@ public boolean isPrimitiveBoolean() { } public boolean isDeprecated() { + return isDeprecatedElement() || inheritsDeprecated(); + } + + private boolean isDeprecatedElement() { return nonNull(getAnnotation(Deprecated.class)); } + private boolean inheritsDeprecated() { + return (isMethod() && inheritsDeprecatedMethod()); + } + + private boolean inheritsDeprecatedMethod() { + return matchingAnySuperMethod( + (ExecutableElement) this.element, + (method, superMethod) -> + env.elements() + .overrides(method, superMethod, (TypeElement) element.getEnclosingElement()) + && TsElement.of(superMethod, env).isDeprecatedElement()); + } + public String getGetterName() { return (isPrimitiveBoolean() ? "is" : "get") + capitalizeFirstLetter(element.getSimpleName().toString()); @@ -786,4 +821,8 @@ public boolean isJsOverlay() { public boolean isUnionMember() { return isJsOverlay() && isMethod() && nonNull(getAnnotation(TsUnionMember.class)); } + + public interface BiPredicate { + boolean test(T t, C c); + } } diff --git a/jsinterop-ts-defs-impl/src/main/java/com/vertispan/tsdefs/impl/model/TsDoc.java b/jsinterop-ts-defs-impl/src/main/java/com/vertispan/tsdefs/impl/model/TsDoc.java index f06b3ed..952851d 100644 --- a/jsinterop-ts-defs-impl/src/main/java/com/vertispan/tsdefs/impl/model/TsDoc.java +++ b/jsinterop-ts-defs-impl/src/main/java/com/vertispan/tsdefs/impl/model/TsDoc.java @@ -32,6 +32,10 @@ public static TsDoc empty() { return TsDoc.of(""); } + public static TsDoc inherited() { + return TsDoc.of(" @inheritDoc"); + } + private TsDoc(String docs) { this.docs = docs; }