From 1e3ba36897d679299fb022f1de9852ffd47c61d2 Mon Sep 17 00:00:00 2001 From: Hadrien Mary Date: Mon, 17 Apr 2017 23:18:10 -0400 Subject: [PATCH 1/4] Add autcompletion framework --- .../script/AbstractScriptLanguage.java | 7 ++ .../scijava/script/AdaptedScriptLanguage.java | 2 + .../org/scijava/script/ScriptLanguage.java | 3 + .../autocompletion/AbstractAutoCompleter.java | 67 +++++++++++++++++++ .../script/autocompletion/AutoCompleter.java | 47 +++++++++++++ .../autocompletion/DefaultAutoCompleter.java | 45 +++++++++++++ .../org/scijava/script/ScriptEngineTest.java | 7 ++ .../org/scijava/script/ScriptFinderTest.java | 7 ++ .../org/scijava/script/ScriptInfoTest.java | 7 ++ 9 files changed, 192 insertions(+) create mode 100644 src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java create mode 100644 src/main/java/org/scijava/script/autocompletion/AutoCompleter.java create mode 100644 src/main/java/org/scijava/script/autocompletion/DefaultAutoCompleter.java diff --git a/src/main/java/org/scijava/script/AbstractScriptLanguage.java b/src/main/java/org/scijava/script/AbstractScriptLanguage.java index 5f52e9ac7..f60a6812d 100644 --- a/src/main/java/org/scijava/script/AbstractScriptLanguage.java +++ b/src/main/java/org/scijava/script/AbstractScriptLanguage.java @@ -35,6 +35,8 @@ import org.scijava.plugin.AbstractRichPlugin; import org.scijava.plugin.PluginInfo; +import org.scijava.script.autocompletion.AutoCompleter; +import org.scijava.script.autocompletion.DefaultAutoCompleter; /** * Abstract superclass for {@link ScriptLanguage} implementations. @@ -70,6 +72,11 @@ public String getLanguageName() { if (info != null) name = info.getName(); return name != null && !name.isEmpty() ? name : inferNameFromClassName(); } + + @Override + public AutoCompleter getAutoCompleter() { + return new DefaultAutoCompleter(getScriptEngine()); + } // -- Helper methods -- diff --git a/src/main/java/org/scijava/script/AdaptedScriptLanguage.java b/src/main/java/org/scijava/script/AdaptedScriptLanguage.java index f0344cdb9..cb26e0241 100644 --- a/src/main/java/org/scijava/script/AdaptedScriptLanguage.java +++ b/src/main/java/org/scijava/script/AdaptedScriptLanguage.java @@ -31,6 +31,8 @@ package org.scijava.script; +import org.scijava.script.autocompletion.DefaultAutoCompleter; +import org.scijava.script.autocompletion.AutoCompleter; import java.util.List; import javax.script.ScriptEngine; diff --git a/src/main/java/org/scijava/script/ScriptLanguage.java b/src/main/java/org/scijava/script/ScriptLanguage.java index 14cf95866..9d77cd588 100644 --- a/src/main/java/org/scijava/script/ScriptLanguage.java +++ b/src/main/java/org/scijava/script/ScriptLanguage.java @@ -31,6 +31,7 @@ package org.scijava.script; +import org.scijava.script.autocompletion.AutoCompleter; import java.util.Collections; import java.util.List; @@ -150,5 +151,7 @@ else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) { default String getEngineVersion() { return "0.0"; } + + public AutoCompleter getAutoCompleter(); } diff --git a/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java b/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java new file mode 100644 index 000000000..a28d26c38 --- /dev/null +++ b/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java @@ -0,0 +1,67 @@ +/* + * #%L + * SciJava Common shared library for SciJava software. + * %% + * Copyright (C) 2009 - 2017 Board of Regents of the University of + * Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck + * Institute of Molecular Cell Biology and Genetics. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.scijava.script.autocompletion; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import javax.script.ScriptEngine; + +/** + * + * @author Hadrien Mary + */ +public abstract class AbstractAutoCompleter implements AutoCompleter { + + protected ScriptEngine engine = null; + + public AbstractAutoCompleter(ScriptEngine engine) { + this.engine = engine; + } + + @Override + public Map autocomplete(String code) { + return autocomplete(code, 0); + } + + @Override + public Map autocomplete(String code, int i) { + Map result = new HashMap<>(); + result.put("matches", new ArrayList<>()); + result.put("startIndex", 0); + return result; + } + + @Override + public ScriptEngine getScriptEngine() { + return this.engine; + } +} diff --git a/src/main/java/org/scijava/script/autocompletion/AutoCompleter.java b/src/main/java/org/scijava/script/autocompletion/AutoCompleter.java new file mode 100644 index 000000000..dd22fd00d --- /dev/null +++ b/src/main/java/org/scijava/script/autocompletion/AutoCompleter.java @@ -0,0 +1,47 @@ +/* + * #%L + * SciJava Common shared library for SciJava software. + * %% + * Copyright (C) 2009 - 2017 Board of Regents of the University of + * Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck + * Institute of Molecular Cell Biology and Genetics. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.scijava.script.autocompletion; + +import java.util.Map; +import javax.script.ScriptEngine; + +/** + * + * @author Hadrien Mary + */ +public interface AutoCompleter { + + public Map autocomplete(String code); + + public Map autocomplete(String code, int i); + + public ScriptEngine getScriptEngine(); +} diff --git a/src/main/java/org/scijava/script/autocompletion/DefaultAutoCompleter.java b/src/main/java/org/scijava/script/autocompletion/DefaultAutoCompleter.java new file mode 100644 index 000000000..bfdd17d27 --- /dev/null +++ b/src/main/java/org/scijava/script/autocompletion/DefaultAutoCompleter.java @@ -0,0 +1,45 @@ +/* + * #%L + * SciJava Common shared library for SciJava software. + * %% + * Copyright (C) 2009 - 2017 Board of Regents of the University of + * Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck + * Institute of Molecular Cell Biology and Genetics. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.scijava.script.autocompletion; + +import javax.script.ScriptEngine; + +/** + * + * @author Hadrien Mary + */ +public class DefaultAutoCompleter extends AbstractAutoCompleter { + + public DefaultAutoCompleter(ScriptEngine engine) { + super(engine); + } + +} diff --git a/src/test/java/org/scijava/script/ScriptEngineTest.java b/src/test/java/org/scijava/script/ScriptEngineTest.java index bce9fe6f2..b620e10ac 100644 --- a/src/test/java/org/scijava/script/ScriptEngineTest.java +++ b/src/test/java/org/scijava/script/ScriptEngineTest.java @@ -31,6 +31,8 @@ package org.scijava.script; +import org.scijava.script.autocompletion.DefaultAutoCompleter; +import org.scijava.script.autocompletion.AutoCompleter; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -99,6 +101,11 @@ public List getNames() { public List getExtensions() { return Arrays.asList("rot13"); } + + @Override + public AutoCompleter getAutoCompleter() { + return new DefaultAutoCompleter(getScriptEngine()); + } } private static class Rot13Engine extends AbstractScriptEngine { diff --git a/src/test/java/org/scijava/script/ScriptFinderTest.java b/src/test/java/org/scijava/script/ScriptFinderTest.java index c24fad50c..87eb922d2 100644 --- a/src/test/java/org/scijava/script/ScriptFinderTest.java +++ b/src/test/java/org/scijava/script/ScriptFinderTest.java @@ -31,6 +31,8 @@ package org.scijava.script; +import org.scijava.script.autocompletion.DefaultAutoCompleter; +import org.scijava.script.autocompletion.AutoCompleter; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -241,6 +243,11 @@ public ScriptEngine getScriptEngine() { throw new IllegalStateException(); } + @Override + public AutoCompleter getAutoCompleter() { + return new DefaultAutoCompleter(getScriptEngine()); + } + } } diff --git a/src/test/java/org/scijava/script/ScriptInfoTest.java b/src/test/java/org/scijava/script/ScriptInfoTest.java index 8d022f748..ec54eaa83 100644 --- a/src/test/java/org/scijava/script/ScriptInfoTest.java +++ b/src/test/java/org/scijava/script/ScriptInfoTest.java @@ -31,6 +31,8 @@ package org.scijava.script; +import org.scijava.script.autocompletion.DefaultAutoCompleter; +import org.scijava.script.autocompletion.AutoCompleter; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; @@ -285,6 +287,11 @@ public List getNames() { public List getExtensions() { return Arrays.asList("bsizes"); } + + @Override + public AutoCompleter getAutoCompleter() { + return new DefaultAutoCompleter(getScriptEngine()); + } } // -- Test script langauge -- From 40962f876ee075f1227d463c0a4de80dae897e65 Mon Sep 17 00:00:00 2001 From: Hadrien Mary Date: Thu, 20 Apr 2017 17:19:35 -0400 Subject: [PATCH 2/4] Add AutoCompletionResult class --- .../script/AbstractScriptLanguage.java | 6 +- .../org/scijava/script/ScriptLanguage.java | 5 +- .../autocompletion/AbstractAutoCompleter.java | 63 ++++++++++++++----- .../script/autocompletion/AutoCompleter.java | 7 +-- .../autocompletion/AutoCompletionResult.java | 36 +++++++++++ .../autocompletion/DefaultAutoCompleter.java | 6 +- .../org/scijava/script/ScriptEngineTest.java | 5 -- .../org/scijava/script/ScriptFinderTest.java | 5 -- .../org/scijava/script/ScriptInfoTest.java | 5 -- 9 files changed, 93 insertions(+), 45 deletions(-) create mode 100644 src/main/java/org/scijava/script/autocompletion/AutoCompletionResult.java diff --git a/src/main/java/org/scijava/script/AbstractScriptLanguage.java b/src/main/java/org/scijava/script/AbstractScriptLanguage.java index f60a6812d..eb0c0b249 100644 --- a/src/main/java/org/scijava/script/AbstractScriptLanguage.java +++ b/src/main/java/org/scijava/script/AbstractScriptLanguage.java @@ -31,6 +31,7 @@ package org.scijava.script; +import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import org.scijava.plugin.AbstractRichPlugin; @@ -72,11 +73,6 @@ public String getLanguageName() { if (info != null) name = info.getName(); return name != null && !name.isEmpty() ? name : inferNameFromClassName(); } - - @Override - public AutoCompleter getAutoCompleter() { - return new DefaultAutoCompleter(getScriptEngine()); - } // -- Helper methods -- diff --git a/src/main/java/org/scijava/script/ScriptLanguage.java b/src/main/java/org/scijava/script/ScriptLanguage.java index 9d77cd588..cd229e1c7 100644 --- a/src/main/java/org/scijava/script/ScriptLanguage.java +++ b/src/main/java/org/scijava/script/ScriptLanguage.java @@ -42,6 +42,7 @@ import org.scijava.plugin.Plugin; import org.scijava.plugin.RichPlugin; import org.scijava.plugin.SingletonPlugin; +import org.scijava.script.autocompletion.DefaultAutoCompleter; import org.scijava.util.VersionUtils; /** @@ -152,6 +153,8 @@ default String getEngineVersion() { return "0.0"; } - public AutoCompleter getAutoCompleter(); + default AutoCompleter getAutoCompleter() { + return new DefaultAutoCompleter(this); + } } diff --git a/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java b/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java index a28d26c38..910566b37 100644 --- a/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java +++ b/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java @@ -31,9 +31,13 @@ package org.scijava.script.autocompletion; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import javax.script.Bindings; +import javax.script.ScriptContext; import javax.script.ScriptEngine; +import org.scijava.script.ScriptLanguage; /** * @@ -41,27 +45,54 @@ */ public abstract class AbstractAutoCompleter implements AutoCompleter { - protected ScriptEngine engine = null; + protected ScriptLanguage scriptLanguage = null; - public AbstractAutoCompleter(ScriptEngine engine) { - this.engine = engine; + public AbstractAutoCompleter(ScriptLanguage scriptLanguage) { + this.scriptLanguage = scriptLanguage; } @Override - public Map autocomplete(String code) { - return autocomplete(code, 0); + public AutoCompletionResult autocomplete(String code, ScriptEngine engine) { + return autocomplete(code, 0, engine); } - + @Override - public Map autocomplete(String code, int i) { - Map result = new HashMap<>(); - result.put("matches", new ArrayList<>()); - result.put("startIndex", 0); - return result; + public AutoCompletionResult autocomplete(String code, int index, ScriptEngine engine) { + + List matches = new ArrayList<>(); + int startIndex = 0; + + // Naive autocompletion with variables in the engine scope + matches.addAll(engineVariablesCompleter(code, index, engine)); + + // Sort matches alphabetcially + Collections.sort(matches, new SortIgnoreCase()); + + // Return results. For now we ignore index and startIndex. + return new AutoCompletionResult(matches, startIndex); } - @Override - public ScriptEngine getScriptEngine() { - return this.engine; + private List engineVariablesCompleter(String code, int index, ScriptEngine engine) { + List matches = new ArrayList<>(); + + Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE); + + for (String key : bindings.keySet()) { + if (key.toLowerCase().startsWith(code.toLowerCase())) { + matches.add(key); + } + } + + return matches; + } + + public class SortIgnoreCase implements Comparator { + + @Override + public int compare(Object o1, Object o2) { + String s1 = (String) o1; + String s2 = (String) o2; + return s1.toLowerCase().compareTo(s2.toLowerCase()); + } } } diff --git a/src/main/java/org/scijava/script/autocompletion/AutoCompleter.java b/src/main/java/org/scijava/script/autocompletion/AutoCompleter.java index dd22fd00d..840f5cb74 100644 --- a/src/main/java/org/scijava/script/autocompletion/AutoCompleter.java +++ b/src/main/java/org/scijava/script/autocompletion/AutoCompleter.java @@ -30,7 +30,6 @@ */ package org.scijava.script.autocompletion; -import java.util.Map; import javax.script.ScriptEngine; /** @@ -39,9 +38,7 @@ */ public interface AutoCompleter { - public Map autocomplete(String code); + public AutoCompletionResult autocomplete(String code, ScriptEngine engine); - public Map autocomplete(String code, int i); - - public ScriptEngine getScriptEngine(); + public AutoCompletionResult autocomplete(String code, int startIndex, ScriptEngine engine); } diff --git a/src/main/java/org/scijava/script/autocompletion/AutoCompletionResult.java b/src/main/java/org/scijava/script/autocompletion/AutoCompletionResult.java new file mode 100644 index 000000000..3e90584e3 --- /dev/null +++ b/src/main/java/org/scijava/script/autocompletion/AutoCompletionResult.java @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.scijava.script.autocompletion; + +import java.util.List; + +/** + * + * @author hadim + */ +public class AutoCompletionResult { + + protected List matches; + protected int startIndex; + + public AutoCompletionResult(List matches) { + this(matches, 0); + } + + public AutoCompletionResult(List matches, int startIndex) { + this.matches = matches; + this.startIndex = startIndex; + } + + public int getStartIndex() { + return this.startIndex; + } + + public List getMatches() { + return this.matches; + } + +} diff --git a/src/main/java/org/scijava/script/autocompletion/DefaultAutoCompleter.java b/src/main/java/org/scijava/script/autocompletion/DefaultAutoCompleter.java index bfdd17d27..902cd4375 100644 --- a/src/main/java/org/scijava/script/autocompletion/DefaultAutoCompleter.java +++ b/src/main/java/org/scijava/script/autocompletion/DefaultAutoCompleter.java @@ -30,7 +30,7 @@ */ package org.scijava.script.autocompletion; -import javax.script.ScriptEngine; +import org.scijava.script.ScriptLanguage; /** * @@ -38,8 +38,8 @@ */ public class DefaultAutoCompleter extends AbstractAutoCompleter { - public DefaultAutoCompleter(ScriptEngine engine) { - super(engine); + public DefaultAutoCompleter(ScriptLanguage scriptLanguage) { + super(scriptLanguage); } } diff --git a/src/test/java/org/scijava/script/ScriptEngineTest.java b/src/test/java/org/scijava/script/ScriptEngineTest.java index b620e10ac..de2f4f0f6 100644 --- a/src/test/java/org/scijava/script/ScriptEngineTest.java +++ b/src/test/java/org/scijava/script/ScriptEngineTest.java @@ -101,11 +101,6 @@ public List getNames() { public List getExtensions() { return Arrays.asList("rot13"); } - - @Override - public AutoCompleter getAutoCompleter() { - return new DefaultAutoCompleter(getScriptEngine()); - } } private static class Rot13Engine extends AbstractScriptEngine { diff --git a/src/test/java/org/scijava/script/ScriptFinderTest.java b/src/test/java/org/scijava/script/ScriptFinderTest.java index 87eb922d2..ee7ef9466 100644 --- a/src/test/java/org/scijava/script/ScriptFinderTest.java +++ b/src/test/java/org/scijava/script/ScriptFinderTest.java @@ -243,11 +243,6 @@ public ScriptEngine getScriptEngine() { throw new IllegalStateException(); } - @Override - public AutoCompleter getAutoCompleter() { - return new DefaultAutoCompleter(getScriptEngine()); - } - } } diff --git a/src/test/java/org/scijava/script/ScriptInfoTest.java b/src/test/java/org/scijava/script/ScriptInfoTest.java index ec54eaa83..ea540f90b 100644 --- a/src/test/java/org/scijava/script/ScriptInfoTest.java +++ b/src/test/java/org/scijava/script/ScriptInfoTest.java @@ -287,11 +287,6 @@ public List getNames() { public List getExtensions() { return Arrays.asList("bsizes"); } - - @Override - public AutoCompleter getAutoCompleter() { - return new DefaultAutoCompleter(getScriptEngine()); - } } // -- Test script langauge -- From e6cb31f628e7f13e05c0b2c6f0eaa764501ccb0f Mon Sep 17 00:00:00 2001 From: Hadrien Mary Date: Thu, 20 Apr 2017 18:44:04 -0400 Subject: [PATCH 3/4] Add autocompletion by inspecting attributes/methods of an object. --- .../autocompletion/AbstractAutoCompleter.java | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java b/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java index 910566b37..4fa376d01 100644 --- a/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java +++ b/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java @@ -30,10 +30,15 @@ */ package org.scijava.script.autocompletion; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; import javax.script.Bindings; import javax.script.ScriptContext; import javax.script.ScriptEngine; @@ -62,8 +67,20 @@ public AutoCompletionResult autocomplete(String code, int index, ScriptEngine en List matches = new ArrayList<>(); int startIndex = 0; - // Naive autocompletion with variables in the engine scope - matches.addAll(engineVariablesCompleter(code, index, engine)); + if (code.endsWith(".")) { + // Autocompletion with all the attributes of the object + matches.addAll(this.engineAttributesCompleter(code, index, engine)); + + } else if (code.contains(".")) { + List codeList = Arrays.asList(code.split("\\.")); + String objectString = (String) codeList.get(codeList.size() - 2); + String fieldBeginWith = (String) codeList.get(codeList.size() - 1); + matches.addAll(this.engineAttributesCompleter(objectString + ".", fieldBeginWith, index, engine)); + + } else { + // Autocompletion with variables in the engine scope + matches.addAll(this.engineVariablesCompleter(code, index, engine)); + } // Sort matches alphabetcially Collections.sort(matches, new SortIgnoreCase()); @@ -80,6 +97,29 @@ private List engineVariablesCompleter(String code, int index, ScriptEngi for (String key : bindings.keySet()) { if (key.toLowerCase().startsWith(code.toLowerCase())) { matches.add(key); + }; + } + return matches; + + } + + private List engineAttributesCompleter(String objectString, int index, ScriptEngine engine) { + return this.engineAttributesCompleter(objectString, "", index, engine); + } + + private List engineAttributesCompleter(String objectString, String fieldBeginWith, int index, ScriptEngine engine) { + List matches = new ArrayList<>(); + + Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE); + + for (String key : bindings.keySet()) { + if (objectString.endsWith(key + ".")) { + Object obj = bindings.get(key); + for (Field field : obj.getClass().getDeclaredFields()) { + if (field.getName().toLowerCase().startsWith(fieldBeginWith.toLowerCase())) { + matches.add(objectString + field.getName()); + } + } } } From 541f46b390cef1d9aff92a149d96709c5623f4a2 Mon Sep 17 00:00:00 2001 From: Hadrien Mary Date: Thu, 20 Apr 2017 18:51:00 -0400 Subject: [PATCH 4/4] Remove duplicates completion results --- .../script/autocompletion/AbstractAutoCompleter.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java b/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java index 4fa376d01..96db64701 100644 --- a/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java +++ b/src/main/java/org/scijava/script/autocompletion/AbstractAutoCompleter.java @@ -30,15 +30,13 @@ */ package org.scijava.script.autocompletion; -import java.lang.reflect.Array; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Map; +import java.util.stream.Collectors; import javax.script.Bindings; import javax.script.ScriptContext; import javax.script.ScriptEngine; @@ -82,7 +80,12 @@ public AutoCompletionResult autocomplete(String code, int index, ScriptEngine en matches.addAll(this.engineVariablesCompleter(code, index, engine)); } - // Sort matches alphabetcially + // Remove duplicates + matches.stream() + .distinct() + .collect(Collectors.toList()); + + // Sort alphabetcially Collections.sort(matches, new SortIgnoreCase()); // Return results. For now we ignore index and startIndex.