1/*
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.internal.jshell.tool;
27
28import java.util.List;
29import static java.util.Comparator.comparing;
30import java.util.Map;
31import java.util.function.BiPredicate;
32import java.util.function.Supplier;
33import static java.util.stream.Collectors.toList;
34import java.util.stream.Stream;
35import jdk.internal.jshell.tool.JShellTool.CompletionProvider;
36import jdk.jshell.SourceCodeAnalysis;
37import jdk.jshell.SourceCodeAnalysis.Suggestion;
38
39class ContinuousCompletionProvider implements CompletionProvider {
40
41    static final BiPredicate<String, String> STARTSWITH_MATCHER = String::startsWith;
42    static final BiPredicate<String, String> PERFECT_MATCHER = String::equals;
43
44    private final Supplier<Map<String, CompletionProvider>> wordCompletionProviderSupplier;
45    private final BiPredicate<String, String> matcher;
46
47    ContinuousCompletionProvider(
48            Map<String, CompletionProvider> wordCompletionProvider,
49            BiPredicate<String, String> matcher) {
50        this(() -> wordCompletionProvider, matcher);
51    }
52
53    ContinuousCompletionProvider(
54            Supplier<Map<String, CompletionProvider>> wordCompletionProviderSupplier,
55            BiPredicate<String, String> matcher) {
56        this.wordCompletionProviderSupplier = wordCompletionProviderSupplier;
57        this.matcher = matcher;
58    }
59
60    @Override
61    public List<Suggestion> completionSuggestions(String input, int cursor, int[] anchor) {
62        String prefix = input.substring(0, cursor);
63        int space = prefix.indexOf(' ');
64
65        Stream<SourceCodeAnalysis.Suggestion> result;
66
67        Map<String, CompletionProvider> wordCompletionProvider = wordCompletionProviderSupplier.get();
68
69        if (space == (-1)) {
70            result = wordCompletionProvider.keySet().stream()
71                    .distinct()
72                    .filter(key -> key.startsWith(prefix))
73                    .map(key -> new JShellTool.ArgSuggestion(key + " "));
74            anchor[0] = 0;
75        } else {
76            String rest = prefix.substring(space + 1);
77            String word = prefix.substring(0, space);
78
79            List<CompletionProvider> candidates = wordCompletionProvider.entrySet().stream()
80                    .filter(e -> matcher.test(e.getKey(), word))
81                    .map(Map.Entry::getValue)
82                    .collect(toList());
83            if (candidates.size() == 1) {
84                result = candidates.get(0).completionSuggestions(rest, cursor - space - 1, anchor).stream();
85            } else {
86                result = Stream.empty();
87            }
88            anchor[0] += space + 1;
89        }
90
91        return result.sorted(comparing(Suggestion::continuation))
92                     .collect(toList());
93    }
94
95}
96