package javarepl.completion; import com.googlecode.totallylazy.Sequence; import com.googlecode.totallylazy.Strings; import com.googlecode.totallylazy.functions.Function1; import static com.googlecode.totallylazy.Sequences.empty; import static com.googlecode.totallylazy.Strings.startsWith; import static com.googlecode.totallylazy.comparators.Comparators.ascending; import static com.googlecode.totallylazy.predicates.Predicates.*; import static javarepl.completion.CompletionCandidate.asCompletionCandidate; public final class TypeCompleter extends Completer { private final TypeResolver typeResolver; public TypeCompleter(TypeResolver typeResolver) { this.typeResolver = typeResolver; } public CompletionResult call(String expression) throws Exception { final int lastSpace = expression.lastIndexOf(" ") + 1; final String packagePart = expression.substring(lastSpace); final int beginIndex = packagePart.lastIndexOf('.') + 1; Sequence<ResolvedPackage> resolvedPackages = typeResolver.packages().filter(where(ResolvedPackage::packageName, startsWith(packagePart))); Sequence<String> classesInPackage = beginIndex > 0 ? typeResolver.packages().filter(where(ResolvedPackage::packageName, equalTo(packagePart.substring(0, beginIndex - 1)))) .flatMap(ResolvedPackage::classes) .map(ResolvedClass::canonicalClassName) .filter(startsWith(packagePart)) : empty(String.class); Sequence<CompletionCandidate> candidates = resolvedPackages.map(ResolvedPackage::packageName).join(classesInPackage) .map(candidatePackagePrefix(beginIndex)) .filter(not(Strings.empty())) .unique() .sort(ascending(String.class)) .map(asCompletionCandidate()); return new CompletionResult(expression, lastSpace + beginIndex, candidates); } private Function1<String, String> candidatePackagePrefix(final int fromIndex) { return item -> { int toIndex = item.indexOf('.', fromIndex); if (toIndex < fromIndex) toIndex = item.length(); return item.substring(fromIndex, toIndex); }; } }