mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
sm support completion. #323
This commit is contained in:
+25
-2
@@ -1,6 +1,9 @@
|
||||
package com.taobao.arthas.core.command.klass100;
|
||||
|
||||
import com.taobao.arthas.core.command.Constants;
|
||||
import com.taobao.arthas.core.shell.cli.CliToken;
|
||||
import com.taobao.arthas.core.shell.cli.Completion;
|
||||
import com.taobao.arthas.core.shell.cli.CompletionUtils;
|
||||
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
|
||||
import com.taobao.arthas.core.shell.command.CommandProcess;
|
||||
import com.taobao.arthas.core.util.matcher.Matcher;
|
||||
@@ -23,6 +26,7 @@ import java.lang.instrument.Instrumentation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.taobao.text.Decoration.bold;
|
||||
@@ -84,7 +88,7 @@ public class SearchMethodCommand extends AnnotatedCommand {
|
||||
|
||||
for (Class<?> clazz : matchedClasses) {
|
||||
Set<String> methodNames = new HashSet<String>();
|
||||
for (Constructor constructor : clazz.getDeclaredConstructors()) {
|
||||
for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
|
||||
if (!methodNameMatcher.matching("<init>")) {
|
||||
continue;
|
||||
}
|
||||
@@ -146,7 +150,7 @@ public class SearchMethodCommand extends AnnotatedCommand {
|
||||
return table;
|
||||
}
|
||||
|
||||
private Element renderConstructor(Constructor constructor) {
|
||||
private Element renderConstructor(Constructor<?> constructor) {
|
||||
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
|
||||
|
||||
table.row(label("declaring-class").style(bold.bold()), label(constructor.getDeclaringClass().getName()))
|
||||
@@ -157,4 +161,23 @@ public class SearchMethodCommand extends AnnotatedCommand {
|
||||
.row(label("exceptions").style(bold.bold()), label(TypeRenderUtils.drawExceptions(constructor)));
|
||||
return table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(Completion completion) {
|
||||
int argumentIndex = CompletionUtils.detectArgumentIndex(completion);
|
||||
|
||||
if(argumentIndex == 1) {
|
||||
if(!CompletionUtils.completeClassName(completion)) {
|
||||
super.complete(completion);
|
||||
}
|
||||
return;
|
||||
}else if(argumentIndex == 2) {
|
||||
if(!CompletionUtils.completeMethodName(completion)) {
|
||||
super.complete(completion);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
super.complete(completion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.taobao.arthas.core.shell.cli;
|
||||
|
||||
import com.taobao.arthas.core.shell.session.Session;
|
||||
import com.taobao.arthas.core.shell.term.Tty;
|
||||
import com.taobao.arthas.core.util.SearchUtils;
|
||||
import com.taobao.arthas.core.util.StringUtils;
|
||||
import com.taobao.arthas.core.util.usage.StyledUsageFormatter;
|
||||
import com.taobao.middleware.cli.CLI;
|
||||
@@ -11,6 +12,7 @@ import io.termd.core.util.Helper;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -54,15 +56,20 @@ public class CompletionUtils {
|
||||
*/
|
||||
public static boolean complete(Completion completion, Collection<String> searchScope) {
|
||||
List<CliToken> tokens = completion.lineTokens();
|
||||
CliToken lastToken = tokens.get(tokens.size() - 1);
|
||||
String lastToken = tokens.get(tokens.size() - 1).value();
|
||||
List<String> candidates = new ArrayList<String>();
|
||||
|
||||
if (StringUtils.isBlank(lastToken)) {
|
||||
lastToken = "";
|
||||
}
|
||||
|
||||
for (String name: searchScope) {
|
||||
if (" ".equals(lastToken.value()) || name.startsWith(lastToken.value())) {
|
||||
if (name.startsWith(lastToken)) {
|
||||
candidates.add(name);
|
||||
}
|
||||
}
|
||||
if (candidates.size() == 1) {
|
||||
completion.complete(candidates.get(0).substring(lastToken.value().length()), true);
|
||||
completion.complete(candidates.get(0).substring(lastToken.length()), true);
|
||||
return true;
|
||||
} else {
|
||||
completion.complete(candidates);
|
||||
@@ -182,6 +189,81 @@ public class CompletionUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean completeMethodName(Completion completion) {
|
||||
List<CliToken> tokens = completion.lineTokens();
|
||||
String lastToken = completion.lineTokens().get(tokens.size() - 1).value();
|
||||
|
||||
// retrieve the class name
|
||||
String className;
|
||||
if (StringUtils.isBlank(lastToken)) {
|
||||
// tokens = { " ", "CLASS_NAME", " "}
|
||||
className = tokens.get(tokens.size() - 2).value();
|
||||
} else {
|
||||
// tokens = { " ", "CLASS_NAME", " ", "PARTIAL_METHOD_NAME"}
|
||||
className = tokens.get(tokens.size() - 3).value();
|
||||
}
|
||||
|
||||
Set<Class<?>> results = SearchUtils.searchClassOnly(completion.session().getInstrumentation(), className, 2);
|
||||
if (results.isEmpty() || results.size() > 1) {
|
||||
// no class found or multiple class found
|
||||
completion.complete(Collections.<String>emptyList());
|
||||
return true;
|
||||
}
|
||||
|
||||
Class<?> clazz = results.iterator().next();
|
||||
|
||||
List<String> res = new ArrayList<String>();
|
||||
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (StringUtils.isBlank(lastToken)) {
|
||||
res.add(method.getName());
|
||||
} else if (method.getName().startsWith(lastToken)) {
|
||||
res.add(method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (res.size() == 1) {
|
||||
completion.complete(res.get(0).substring(lastToken.length()), true);
|
||||
return true;
|
||||
} else {
|
||||
CompletionUtils.complete(completion, res);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 推断输入到哪一个 argument
|
||||
* @param completion
|
||||
* @return
|
||||
*/
|
||||
public static int detectArgumentIndex(Completion completion) {
|
||||
List<CliToken> tokens = completion.lineTokens();
|
||||
CliToken lastToken = tokens.get(tokens.size() - 1);
|
||||
|
||||
if (lastToken.value().startsWith("-") || lastToken.value().startsWith("--")) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank((lastToken.value())) && tokens.size() == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tokenCount = 0;
|
||||
|
||||
for (CliToken token : tokens) {
|
||||
if (StringUtils.isBlank(token.value()) || token.value().startsWith("-") || token.value().startsWith("--")) {
|
||||
// filter irrelevant tokens
|
||||
continue;
|
||||
}
|
||||
tokenCount++;
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank((lastToken.value())) && tokens.size() != 1) {
|
||||
tokenCount++;
|
||||
}
|
||||
return tokenCount;
|
||||
}
|
||||
|
||||
public static void completeShortOption(Completion completion, CliToken lastToken, List<Option> options) {
|
||||
String prefix = lastToken.value().substring(1);
|
||||
List<String> candidates = new ArrayList<String>();
|
||||
|
||||
Reference in New Issue
Block a user