Skip to content

Commit a6a978d

Browse files
committed
Omit internal results from docs search unless requested.
1 parent 8a18f74 commit a6a978d

File tree

2 files changed

+99
-18
lines changed

2 files changed

+99
-18
lines changed

src/main/java/org/javacord/bot/commands/DocsCommand.java

Lines changed: 84 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,33 @@
1414
import java.io.IOException;
1515
import java.io.InputStream;
1616
import java.util.Arrays;
17+
import java.util.Collections;
1718
import java.util.Comparator;
19+
import java.util.HashSet;
1820
import java.util.List;
1921
import java.util.Map;
22+
import java.util.Set;
23+
import java.util.concurrent.CompletableFuture;
2024
import java.util.stream.Collectors;
2125

2226
/**
2327
* The !docs command which is used to show links to Javacord's JavaDocs.
2428
*/
2529
public class DocsCommand implements CommandExecutor {
2630

31+
/**
32+
* The parameters that indicate searching for class names only.
33+
*/
34+
private static final Set<String> classParams = new HashSet<>(Arrays.asList("classes", "class", "c"));
35+
/**
36+
* The parameters that indicate searching for method names only.
37+
*/
38+
private static final Set<String> methodParams = new HashSet<>(Arrays.asList("methods", "method", "m"));
39+
/**
40+
* The parameters that indicate also searching internal packages and the core docs.
41+
*/
42+
private static final Set<String> includeAllParams = new HashSet<>(Arrays.asList("all", "a"));
43+
2744
/**
2845
* Executes the {@code !docs} command.
2946
*
@@ -42,16 +59,21 @@ public void onCommand(TextChannel channel, String[] args) throws IOException {
4259
.addField("Latest release version", "https://docs.javacord.org/api/v/latest")
4360
.addField("Latest snapshot", "https://docs.javacord.org/api/build/latest")
4461
.addField("Hint", "You can search the docs using `!docs [method|class] <search>`");
45-
} else { // Search
46-
if (args[0].matches("(classes|class|c)")) { // Search for a class
47-
String searchString = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
48-
populateClasses(channel.getApi(), embed, searchString);
49-
} else if (args[0].matches("(methods|method|m)")) { // Search for a method
50-
String searchString = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
51-
populateMethods(channel.getApi(), embed, searchString);
62+
} else if (args.length == 1) { // Basic search - methods without internals
63+
populateMethods(channel.getApi(), embed, args[0], false);
64+
} else { // Extended search
65+
if (classParams.contains(args[0])) { // Search for a class
66+
boolean searchAll = args.length > 2 && includeAllParams.contains(args[1]);
67+
String searchString = String.join(" ", Arrays.copyOfRange(args, searchAll ? 2 : 1, args.length));
68+
populateClasses(channel.getApi(), embed, searchString, searchAll);
69+
} else if (methodParams.contains(args[0])) { // Search for a method
70+
boolean searchAll = args.length > 2 && includeAllParams.contains(args[1]);
71+
String searchString = String.join(" ", Arrays.copyOfRange(args, searchAll ? 2 : 1, args.length));
72+
populateMethods(channel.getApi(), embed, searchString, searchAll);
5273
} else { // Search for a method
53-
String searchString = String.join(" ", args);
54-
populateMethods(channel.getApi(), embed, searchString);
74+
boolean searchAll = includeAllParams.contains(args[0]);
75+
String searchString = String.join(" ", Arrays.copyOfRange(args, searchAll ? 1 : 0, args.length));
76+
populateMethods(channel.getApi(), embed, searchString, searchAll);
5577
}
5678
}
5779
channel.sendMessage(embed).join();
@@ -70,10 +92,22 @@ public void onCommand(TextChannel channel, String[] args) throws IOException {
7092
* @param embed The embed to populate.
7193
* @param searchString A search string.
7294
*/
73-
private void populateMethods(DiscordApi api, EmbedBuilder embed, String searchString) {
74-
Map<String, List<JavadocMethod>> methods = new JavadocParser(api, JavadocParser.getLatestJavaDocs(api).join())
75-
.getMethods().join().stream()
95+
private void populateMethods(DiscordApi api, EmbedBuilder embed, String searchString, boolean includeAll) {
96+
CompletableFuture<Set<JavadocMethod>> apiMethods = JavadocParser.getLatestJavaDocs(api)
97+
.thenApply(urlString -> new JavadocParser(api, urlString))
98+
.thenCompose(JavadocParser::getMethods);
99+
CompletableFuture<Set<JavadocMethod>> coreMethods = (includeAll)
100+
? JavadocParser.getLatestCoreJavaDocs(api)
101+
.thenApply(urlString -> new JavadocParser(api, urlString))
102+
.thenCompose(JavadocParser::getMethods)
103+
: CompletableFuture.completedFuture(Collections.emptySet());
104+
105+
Map<String, List<JavadocMethod>> methods = apiMethods.thenCombine(coreMethods, this::unionOf).join().stream()
76106
.filter(method -> method.getFullName().toLowerCase().contains(searchString.toLowerCase()))
107+
.filter(method -> {
108+
String packageName = method.getPackageName();
109+
return includeAll || !(packageName.endsWith(".internal") || packageName.contains(".internal."));
110+
})
77111
.sorted(Comparator.comparingInt(method -> method.getName().length()))
78112
.collect(Collectors.groupingBy(JavadocMethod::getClassName));
79113

@@ -115,17 +149,47 @@ private void populateMethods(DiscordApi api, EmbedBuilder embed, String searchSt
115149
}
116150
}
117151

152+
/**
153+
* Union operation for sets.
154+
*
155+
* @param set1 First set.
156+
* @param set2 Second set.
157+
* @param <T> Type of set content.
158+
* @return The union of the two sets.
159+
*/
160+
private <T> Set<T> unionOf(Set<T> set1, Set<T> set2) {
161+
if (set2.isEmpty()) {
162+
return set1;
163+
} else {
164+
Set<T> union = new HashSet<>(set1);
165+
union.addAll(set2);
166+
return union;
167+
}
168+
}
169+
118170
/**
119171
* Populates the classes field inside the given embed.
120172
*
121173
* @param api A discord api instance.
122174
* @param embed The embed to populate.
123175
* @param searchString A search string.
124176
*/
125-
private void populateClasses(DiscordApi api, EmbedBuilder embed, String searchString) {
126-
List<JavadocClass> classes = new JavadocParser(api, JavadocParser.getLatestJavaDocs(api).join())
127-
.getClasses().join().stream()
177+
private void populateClasses(DiscordApi api, EmbedBuilder embed, String searchString, boolean includeAll) {
178+
CompletableFuture<Set<JavadocClass>> apiClasses = JavadocParser.getLatestJavaDocs(api)
179+
.thenApply(urlString -> new JavadocParser(api, urlString))
180+
.thenCompose(JavadocParser::getClasses);
181+
CompletableFuture<Set<JavadocClass>> coreClasses = (includeAll)
182+
? JavadocParser.getLatestCoreJavaDocs(api)
183+
.thenApply(urlString -> new JavadocParser(api, urlString))
184+
.thenCompose(JavadocParser::getClasses)
185+
: CompletableFuture.completedFuture(Collections.emptySet());
186+
187+
List<JavadocClass> classes = apiClasses.thenCombine(coreClasses, this::unionOf).join().stream()
128188
.filter(clazz -> clazz.getName().toLowerCase().contains(searchString.toLowerCase()))
189+
.filter(clazz -> {
190+
String packageName = clazz.getPackageName();
191+
return includeAll || !(packageName.endsWith(".internal") || packageName.contains(".internal."));
192+
})
129193
.sorted(Comparator.comparingInt(clazz -> clazz.getName().length()))
130194
.collect(Collectors.toList());
131195

@@ -138,19 +202,22 @@ private void populateClasses(DiscordApi api, EmbedBuilder embed, String searchSt
138202
StringBuilder strBuilder = new StringBuilder();
139203
int counter = 0;
140204
for (JavadocClass clazz : classes) {
205+
if (strBuilder.length() > 0) {
206+
strBuilder.append(", ");
207+
}
141208
strBuilder.append("[")
142209
.append(clazz.getName())
143210
.append("](")
144211
.append(clazz.getFullUrl())
145-
.append("), ");
212+
.append(")");
146213
counter++;
147214
if (strBuilder.length() > 1950) { // Prevent hitting the description size limit
148215
break;
149216
}
150217
}
151218

152219
if (classes.size() - counter > 0) {
153-
strBuilder.append("and ").append(classes.size() - counter).append(" more ...");
220+
strBuilder.append("\nand ").append(classes.size() - counter).append(" more ...");
154221
}
155222

156223
embed.setDescription(strBuilder.toString());

src/main/java/org/javacord/bot/util/javadoc/parser/JavadocParser.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,24 @@ public JavadocParser(DiscordApi api, String url) {
4343
* @return The latest JavaDoc link.
4444
*/
4545
public static CompletableFuture<String> getLatestJavaDocs(DiscordApi api) {
46+
return getJavadocUrl(api, "https://docs.javacord.org/api/");
47+
}
48+
49+
/**
50+
* Gets the latest core JavaDoc link.
51+
*
52+
* @param api A discord api instance.
53+
* @return The latest core JavaDoc link.
54+
*/
55+
public static CompletableFuture<String> getLatestCoreJavaDocs(DiscordApi api) {
56+
return getJavadocUrl(api, "https://docs.javacord.org/core/");
57+
}
58+
59+
private static CompletableFuture<String> getJavadocUrl(DiscordApi api, String url) {
4660
return CompletableFuture.supplyAsync(() -> {
4761
try {
4862
Request request = new Request.Builder()
49-
.url("https://docs.javacord.org/api/")
63+
.url(url)
5064
.build();
5165

5266
try (Response response = client.newCall(request).execute()) {

0 commit comments

Comments
 (0)