|
|
@@ -36,6 +36,7 @@ import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Objects;
|
|
|
import java.util.Optional;
|
|
|
+import java.util.regex.Pattern;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
public class JavadocExtractor {
|
|
|
@@ -43,9 +44,16 @@ public class JavadocExtractor {
|
|
|
private final JavaClassResolver resolver;
|
|
|
private final Map<String, ParsedJavaClass> cache = new HashMap<>();
|
|
|
|
|
|
- private static final String GPLv2 = "* This code is free software; you can redistribute it and/or modify it"+
|
|
|
- "\n * under the terms of the GNU General Public License version 2 only, as"+
|
|
|
- "\n * published by the Free Software Foundation.";
|
|
|
+ private static final String GPLv2 = "This code is free software; you can redistribute it and/or" +
|
|
|
+ " modify it under the terms of the GNU General Public License version 2 only, as published" +
|
|
|
+ " by the Free Software Foundation.";
|
|
|
+
|
|
|
+ private static final String ESv2 = "Copyright Elasticsearch B.V. and/or licensed to Elasticsearch" +
|
|
|
+ " B.V. under one or more contributor license agreements. Licensed under the Elastic License 2.0" +
|
|
|
+ " and the Server Side Public License, v 1; you may not use this file except in compliance with," +
|
|
|
+ " at your election, the Elastic License 2.0 or the Server Side Public License, v 1.";
|
|
|
+
|
|
|
+ private static final String[] LICENSES = new String[]{GPLv2, ESv2};
|
|
|
|
|
|
public JavadocExtractor(JavaClassResolver resolver) {
|
|
|
this.resolver = resolver;
|
|
|
@@ -58,7 +66,7 @@ public class JavadocExtractor {
|
|
|
return parsed;
|
|
|
}
|
|
|
InputStream classStream = resolver.openClassFile(className);
|
|
|
- parsed = new ParsedJavaClass(GPLv2);
|
|
|
+ parsed = new ParsedJavaClass();
|
|
|
if (classStream != null) {
|
|
|
ClassFileVisitor visitor = new ClassFileVisitor();
|
|
|
CompilationUnit cu = StaticJavaParser.parse(classStream);
|
|
|
@@ -69,25 +77,34 @@ public class JavadocExtractor {
|
|
|
}
|
|
|
|
|
|
public static class ParsedJavaClass {
|
|
|
+ private static final Pattern LICENSE_CLEANUP = Pattern.compile("\\s*\n\\s*\\*");
|
|
|
+
|
|
|
public final Map<MethodSignature, ParsedMethod> methods;
|
|
|
public final Map<String, String> fields;
|
|
|
public final Map<List<String>, ParsedMethod> constructors;
|
|
|
- private final String license;
|
|
|
+ private final String[] licenses;
|
|
|
private boolean valid = false;
|
|
|
private boolean validated = false;
|
|
|
|
|
|
- public ParsedJavaClass(String license) {
|
|
|
+ public ParsedJavaClass(String ... licenses) {
|
|
|
methods = new HashMap<>();
|
|
|
fields = new HashMap<>();
|
|
|
constructors = new HashMap<>();
|
|
|
- this.license = license;
|
|
|
+ if (licenses.length > 0) {
|
|
|
+ this.licenses = licenses;
|
|
|
+ } else {
|
|
|
+ this.licenses = LICENSES;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void validateLicense(Optional<Comment> license) {
|
|
|
if (validated) {
|
|
|
throw new IllegalStateException("Cannot double validate the license");
|
|
|
}
|
|
|
- this.valid = license.map(Comment::getContent).orElse("").contains(this.license);
|
|
|
+ String header = license.map(c -> LICENSE_CLEANUP.matcher(c.getContent()).replaceAll("").trim()).orElse("");
|
|
|
+ for (String validLicense : licenses) {
|
|
|
+ valid |= header.contains(validLicense);
|
|
|
+ }
|
|
|
validated = true;
|
|
|
}
|
|
|
|
|
|
@@ -95,6 +112,18 @@ public class JavadocExtractor {
|
|
|
return methods.get(new MethodSignature(name, parameterTypes));
|
|
|
}
|
|
|
|
|
|
+ public ParsedMethod getAugmentedMethod(String methodName, String receiverType, List<String> parameterTypes) {
|
|
|
+ List<String> parameterKey = new ArrayList<>(parameterTypes.size() + 1);
|
|
|
+ parameterKey.add(receiverType);
|
|
|
+ parameterKey.addAll(parameterTypes);
|
|
|
+
|
|
|
+ ParsedMethod augmented = getMethod(methodName, parameterKey);
|
|
|
+ if (augmented == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return augmented.asAugmented();
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public String toString() {
|
|
|
return "ParsedJavaClass{" +
|
|
|
@@ -112,7 +141,7 @@ public class JavadocExtractor {
|
|
|
declaration.getJavadoc().map(JavadocExtractor::clean).orElse(null),
|
|
|
declaration.getParameters()
|
|
|
.stream()
|
|
|
- .map(p -> p.getName().asString())
|
|
|
+ .map(p -> stripTypeParameters(p.getName().asString()))
|
|
|
.collect(Collectors.toList())
|
|
|
)
|
|
|
);
|
|
|
@@ -134,26 +163,6 @@ public class JavadocExtractor {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- private static String stripTypeParameters(String type) {
|
|
|
- int start = 0;
|
|
|
- int count = 0;
|
|
|
- for (int i=0; i<type.length(); i++) {
|
|
|
- char c = type.charAt(i);
|
|
|
- if (c == '<') {
|
|
|
- if (start == 0) {
|
|
|
- start = i;
|
|
|
- }
|
|
|
- count++;
|
|
|
- } else if (c == '>') {
|
|
|
- count--;
|
|
|
- if (count == 0) {
|
|
|
- return type.substring(0, start);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return type;
|
|
|
- }
|
|
|
-
|
|
|
public ParsedMethod getConstructor(List<String> parameterTypes) {
|
|
|
return constructors.get(parameterTypes);
|
|
|
}
|
|
|
@@ -172,6 +181,26 @@ public class JavadocExtractor {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private static String stripTypeParameters(String type) {
|
|
|
+ int start = 0;
|
|
|
+ int count = 0;
|
|
|
+ for (int i=0; i<type.length(); i++) {
|
|
|
+ char c = type.charAt(i);
|
|
|
+ if (c == '<') {
|
|
|
+ if (start == 0) {
|
|
|
+ start = i;
|
|
|
+ }
|
|
|
+ count++;
|
|
|
+ } else if (c == '>') {
|
|
|
+ count--;
|
|
|
+ if (count == 0) {
|
|
|
+ return type.substring(0, start);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return type;
|
|
|
+ }
|
|
|
+
|
|
|
public static class MethodSignature {
|
|
|
public final String name;
|
|
|
public final List<String> parameterTypes;
|
|
|
@@ -186,7 +215,7 @@ public class JavadocExtractor {
|
|
|
declaration.getNameAsString(),
|
|
|
declaration.getParameters()
|
|
|
.stream()
|
|
|
- .map(p -> p.getType().asString())
|
|
|
+ .map(p -> stripTypeParameters(p.getType().asString()))
|
|
|
.collect(Collectors.toList())
|
|
|
);
|
|
|
}
|
|
|
@@ -215,6 +244,16 @@ public class JavadocExtractor {
|
|
|
this.parameterNames = parameterNames;
|
|
|
}
|
|
|
|
|
|
+ public ParsedMethod asAugmented() {
|
|
|
+ if (parameterNames.size() == 0) {
|
|
|
+ throw new IllegalStateException("Cannot augment without receiver: javadoc=" + javadoc);
|
|
|
+ }
|
|
|
+ return new ParsedMethod(
|
|
|
+ javadoc == null ? null : javadoc.asAugmented(parameterNames.get(0)),
|
|
|
+ new ArrayList<>(parameterNames.subList(1, parameterNames.size()))
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
public boolean isEmpty() {
|
|
|
return (javadoc == null || javadoc.isEmpty()) && parameterNames.isEmpty();
|
|
|
}
|
|
|
@@ -235,6 +274,17 @@ public class JavadocExtractor {
|
|
|
this.description = description;
|
|
|
}
|
|
|
|
|
|
+ public ParsedJavadoc asAugmented(String receiverName) {
|
|
|
+ if (param == null) {
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ ParsedJavadoc augmented = new ParsedJavadoc(description);
|
|
|
+ augmented.param.putAll(param);
|
|
|
+ augmented.param.remove(receiverName);
|
|
|
+ augmented.thrws = thrws;
|
|
|
+ return augmented;
|
|
|
+ }
|
|
|
+
|
|
|
public boolean isEmpty() {
|
|
|
return param.size() == 0 &&
|
|
|
(description == null || description.isEmpty()) &&
|