You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2020/09/16 07:17:15 UTC
[camel] 03/04: CAMEL-15478: Java source parser should resolve
return type that may be generic and parameterized.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch api
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 6f6c1b98802e0cc21a73820696bec59c0de52076
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Sep 16 09:03:28 2020 +0200
CAMEL-15478: Java source parser should resolve return type that may be generic and parameterized.
---
.../org/apache/camel/maven/JavaSourceParser.java | 187 ++++++++-------------
1 file changed, 67 insertions(+), 120 deletions(-)
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavaSourceParser.java b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavaSourceParser.java
index a05596e..dbc3fa0 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavaSourceParser.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavaSourceParser.java
@@ -57,65 +57,6 @@ public class JavaSourceParser {
private String apiDescription;
private final Map<String, String> methodDescriptions = new HashMap<>();
- private static String resolveParameterizedType(
- AbstractGenericCapableJavaSource clazz, MethodSource ms, ParameterSource ps, Type type) {
- String answer = resolveType(clazz, clazz, ms, type);
-
- if (type.isParameterized()) {
- // for parameterized types then it can get complex if they are variables (T, T extends Foo etc)
- // or if there are no bounds for these types which we then can't resolve.
- List<Type> types = type.getTypeArguments();
- boolean bounds = false;
- boolean found = false;
- for (Type t : types) {
- if (hasTypeVariableBounds(ms, clazz, t.getName())) {
- bounds = true;
- // okay now it gets complex as we have a type like T which is a type variable and we need to resolve that into
- // what base class that is
- String tn = resolveTypeVariable(ms, clazz, t.getName());
- if (tn != null) {
- answer = answer.replace(t.getName(), tn);
- found = true;
- }
- }
- }
- if (!bounds && !found) {
- // argh this is getting complex, it may be T or just java.lang.String but this **** generics and roaster
- // does not make this easy, so let see if we can find out if all the types are a qualified type or only a variable
- boolean fqn = types.stream().allMatch(t -> {
- // if its from java itself then its okay
- if (t.getQualifiedName().startsWith("java")) {
- return true;
- }
- // okay lets assume its a type variable if the name is upper case only
- boolean upperOnly = isUpperCaseOnly(t.getName());
- return !upperOnly && t.getQualifiedName().indexOf('.') != -1;
- });
- if (!fqn) {
- // remove generics we could not resolve that even if we have bounds information
- bounds = true;
- found = false;
- }
- }
- if (bounds && !found) {
- // remove generics we could not resolve that even if we have bounds information
- answer = type.getQualifiedName();
- }
- } else if (ms.hasTypeVariable(answer) || clazz.hasTypeVariable(answer)) {
- // okay now it gets complex as we have a type like T which is a type variable and we need to resolve that into
- // what base class that is
- answer = resolveTypeVariable(ms, clazz, answer);
- }
- if ((ps != null && ps.isVarArgs()) || type.isArray()) {
- // the old way with javadoc did not use varargs in the signature, so lets transform this to an array style
- answer = answer + "[]";
- }
-
- // remove java.lang. prefix as it should not be there
- answer = answer.replaceAll("java.lang.", "");
- return answer;
- }
-
@SuppressWarnings("unchecked")
public synchronized void parse(InputStream in, String innerClass) throws Exception {
AbstractGenericCapableJavaSource rootClazz = (AbstractGenericCapableJavaSource) Roaster.parse(in);
@@ -165,7 +106,7 @@ public class JavaSourceParser {
methodDescriptions.put(ms.getName(), doc);
}
- String result = resolveParameterizedType(clazz, ms, null, ms.getReturnType());
+ String result = resolveParameterizedType(rootClazz, clazz, ms, null, ms.getReturnType());
if (result.isEmpty()) {
result = "void";
}
@@ -181,63 +122,9 @@ public class JavaSourceParser {
for (int i = 0; i < list.size(); i++) {
ParameterSource ps = list.get(i);
String name = ps.getName();
- String type = resolveType(rootClazz, clazz, ms, ps.getType());
+ String type = resolveParameterizedType(rootClazz, clazz, ms, ps, ps.getType());
LOG.trace("Parsing parameter #{} ({} {})", i, type, name);
- // TODO: Call that other method
- if (ps.getType().isParameterized()) {
- // for parameterized types then it can get complex if they are variables (T, T extends Foo etc)
- // or if there are no bounds for these types which we then can't resolve.
- List<Type> types = ps.getType().getTypeArguments();
- boolean bounds = false;
- boolean found = false;
- for (Type t : types) {
- if (hasTypeVariableBounds(ms, clazz, t.getName())) {
- bounds = true;
- // okay now it gets complex as we have a type like T which is a type variable and we need to resolve that into
- // what base class that is
- String tn = resolveTypeVariable(ms, clazz, t.getName());
- if (tn != null) {
- type = type.replace(t.getName(), tn);
- found = true;
- }
- }
- }
- if (!bounds && !found) {
- // argh this is getting complex, it may be T or just java.lang.String but this **** generics and roaster
- // does not make this easy, so let see if we can find out if all the types are a qualified type or only a variable
- boolean fqn = types.stream().allMatch(t -> {
- // if its from java itself then its okay
- if (t.getQualifiedName().startsWith("java")) {
- return true;
- }
- // okay lets assume its a type variable if the name is upper case only
- boolean upperOnly = isUpperCaseOnly(t.getName());
- return !upperOnly && t.getQualifiedName().indexOf('.') != -1;
- });
- if (!fqn) {
- // remove generics we could not resolve that even if we have bounds information
- bounds = true;
- found = false;
- }
- }
- if (bounds && !found) {
- // remove generics we could not resolve that even if we have bounds information
- type = ps.getType().getQualifiedName();
- }
- } else if (ms.hasTypeVariable(type) || clazz.hasTypeVariable(type)) {
- // okay now it gets complex as we have a type like T which is a type variable and we need to resolve that into
- // what base class that is
- type = resolveTypeVariable(ms, clazz, type);
- }
- if (ps.isVarArgs() || ps.getType().isArray()) {
- // the old way with javadoc did not use varargs in the signature, so lets transform this to an array style
- type = type + "[]";
- }
-
- // remove all java.lang. prefixes
- type = type.replaceAll("java.lang.", "");
-
sb.append(type);
sb.append(" ").append(name);
if (i < list.size() - 1) {
@@ -264,13 +151,64 @@ public class JavaSourceParser {
}
}
- private static boolean isUpperCaseOnly(String name) {
- for (int i = 0; i < name.length(); i++) {
- if (!Character.isUpperCase(name.charAt(i))) {
- return false;
+ private static String resolveParameterizedType(
+ AbstractGenericCapableJavaSource rootClazz, AbstractGenericCapableJavaSource clazz, MethodSource ms,
+ ParameterSource ps, Type type) {
+ String answer = resolveType(rootClazz, clazz, ms, type);
+
+ if (type.isParameterized()) {
+ // for parameterized types then it can get complex if they are variables (T, T extends Foo etc)
+ // or if there are no bounds for these types which we then can't resolve.
+ List<Type> types = type.getTypeArguments();
+ boolean bounds = false;
+ boolean found = false;
+ for (Type t : types) {
+ if (hasTypeVariableBounds(ms, clazz, t.getName())) {
+ bounds = true;
+ // okay now it gets complex as we have a type like T which is a type variable and we need to resolve that into
+ // what base class that is
+ String tn = resolveTypeVariable(ms, clazz, t.getName());
+ if (tn != null) {
+ answer = answer.replace(t.getName(), tn);
+ found = true;
+ }
+ }
+ }
+ if (!bounds && !found) {
+ // argh this is getting complex, it may be T or just java.lang.String but this **** generics and roaster
+ // does not make this easy, so let see if we can find out if all the types are a qualified type or only a variable
+ boolean fqn = types.stream().allMatch(t -> {
+ // if its from java itself then its okay
+ if (t.getQualifiedName().startsWith("java")) {
+ return true;
+ }
+ // okay lets assume its a type variable if the name is upper case only
+ boolean upperOnly = isUpperCaseOnly(t.getName());
+ return !upperOnly && t.getQualifiedName().indexOf('.') != -1;
+ });
+ if (!fqn) {
+ // remove generics we could not resolve that even if we have bounds information
+ bounds = true;
+ found = false;
+ }
}
+ if (bounds && !found) {
+ // remove generics we could not resolve that even if we have bounds information
+ answer = type.getQualifiedName();
+ }
+ } else if (ms.hasTypeVariable(answer) || clazz.hasTypeVariable(answer)) {
+ // okay now it gets complex as we have a type like T which is a type variable and we need to resolve that into
+ // what base class that is
+ answer = resolveTypeVariable(ms, clazz, answer);
}
- return true;
+ if ((ps != null && ps.isVarArgs()) || type.isArray()) {
+ // the old way with javadoc did not use varargs in the signature, so lets transform this to an array style
+ answer = answer + "[]";
+ }
+
+ // remove java.lang. prefix as it should not be there
+ answer = answer.replaceAll("java.lang.", "");
+ return answer;
}
private static boolean hasTypeVariableBounds(MethodSource ms, AbstractGenericCapableJavaSource clazz, String type) {
@@ -483,6 +421,15 @@ public class JavaSourceParser {
return desc;
}
+ private static boolean isUpperCaseOnly(String name) {
+ for (int i = 0; i < name.length(); i++) {
+ if (!Character.isUpperCase(name.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
public void reset() {
methods.clear();
methodText.clear();