diff --git a/app/.classpath b/app/.classpath
index d556d28fe..77cb666a1 100644
--- a/app/.classpath
+++ b/app/.classpath
@@ -55,5 +55,6 @@
+
diff --git a/app/src/cc/arduino/autocomplete/ArduinoCompletionsList.java b/app/src/cc/arduino/autocomplete/ArduinoCompletionsList.java
new file mode 100644
index 000000000..8f8be5056
--- /dev/null
+++ b/app/src/cc/arduino/autocomplete/ArduinoCompletionsList.java
@@ -0,0 +1,61 @@
+package cc.arduino.autocomplete;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ArduinoCompletionsList extends ArrayList {
+}
+
+class ArduinoCompletion {
+ ArduinoCompletionDetail completion;
+ String type;
+
+ public ArduinoCompletionDetail getCompletion() {
+ return completion;
+ }
+
+ public String getType() {
+ return type;
+ }
+}
+
+class ArduinoCompletionDetail {
+ List chunks;
+ String brief;
+
+ public List getChunks() {
+ return chunks;
+ }
+
+ public String getBrief() {
+ return brief;
+ }
+}
+
+class CompletionChunk {
+ String typedtext;
+ String t;
+ String placeholder;
+ String res;
+ ArduinoCompletionDetail optional;
+
+ public String getTypedtext() {
+ return typedtext;
+ }
+
+ public String getT() {
+ return t;
+ }
+
+ public String getPlaceholder() {
+ return placeholder;
+ }
+
+ public String getRes() {
+ return res;
+ }
+
+ public ArduinoCompletionDetail getOptional() {
+ return optional;
+ }
+}
\ No newline at end of file
diff --git a/app/src/cc/arduino/autocomplete/BaseCCompletionProvider.java b/app/src/cc/arduino/autocomplete/BaseCCompletionProvider.java
index cf0b1dae1..7c10d256a 100755
--- a/app/src/cc/arduino/autocomplete/BaseCCompletionProvider.java
+++ b/app/src/cc/arduino/autocomplete/BaseCCompletionProvider.java
@@ -7,7 +7,7 @@ import org.fife.ui.autocomplete.DefaultCompletionProvider;
* @author Ricardo JL Rufino (ricardo@criativasoft.com.br)
* @date 28/04/2017
*/
-public class BaseCCompletionProvider extends DefaultCompletionProvider{
+public class BaseCCompletionProvider extends DefaultCompletionProvider {
@Override
protected boolean isValidChar(char ch) {
diff --git a/app/src/cc/arduino/autocomplete/ClangCompletionProvider.java b/app/src/cc/arduino/autocomplete/ClangCompletionProvider.java
new file mode 100644
index 000000000..6a46d5ee6
--- /dev/null
+++ b/app/src/cc/arduino/autocomplete/ClangCompletionProvider.java
@@ -0,0 +1,88 @@
+package cc.arduino.autocomplete;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.text.BadLocationException;
+import javax.swing.text.JTextComponent;
+
+import org.fife.ui.autocomplete.Completion;
+import org.fife.ui.autocomplete.TemplateCompletion;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import processing.app.Editor;
+import processing.app.EditorTab;
+
+public class ClangCompletionProvider extends BaseCCompletionProvider {
+
+ private Editor editor;
+
+ public ClangCompletionProvider(Editor e) {
+ super();
+ editor = e;
+ }
+
+ @Override
+ public List getCompletionByInputText(String inputText) {
+ System.out.println("INPUTTEXT: " + inputText);
+ return super.getCompletionByInputText(inputText);
+ }
+
+ @Override
+ protected List getCompletionsImpl(JTextComponent textarea) {
+
+ // Retrieve current line and column
+ EditorTab tab = editor.getCurrentTab();
+ int line, col;
+ try {
+ int pos = tab.getTextArea().getCaretPosition();
+ line = tab.getTextArea().getLineOfOffset(pos);
+ col = pos - tab.getTextArea().getLineStartOffset(line);
+ line++;
+ col++;
+ } catch (BadLocationException e1) {
+ // Should never happen...
+ e1.printStackTrace();
+ return completions;
+ }
+
+ try {
+ // Run codecompletion engine
+ String out = editor.getSketchController()
+ .codeComplete(tab.getSketchFile(), line, col);
+
+ List res = new ArrayList<>();
+ res.add(new TemplateCompletion(this, "for", "interate over array",
+ "for (int ${i} = 0; ${i} < ${array}.length; ${i}++) {\n ${cursor}\n}"));
+
+ // Parse engine output and build code completions
+ ObjectMapper mapper = new ObjectMapper();
+ ArduinoCompletionsList allCc;
+ allCc = mapper.readValue(out, ArduinoCompletionsList.class);
+ for (ArduinoCompletion cc : allCc) {
+ if (cc.type.equals("macro")) {
+ // for now skip macro
+ continue;
+ }
+ String returnType;
+ String typedText;
+ String template = "";
+ for (CompletionChunk chunk : cc.completion.chunks) {
+ if (chunk.t != null) {
+ template += "t";
+ }
+ if (chunk.res != null) {
+ returnType = chunk.res;
+ }
+ if (chunk.typedtext != null) {
+ typedText = chunk.typedtext;
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return completions;
+ }
+}
diff --git a/app/src/processing/app/EditorTab.java b/app/src/processing/app/EditorTab.java
index 7fe2439cd..9765ba4f6 100644
--- a/app/src/processing/app/EditorTab.java
+++ b/app/src/processing/app/EditorTab.java
@@ -58,6 +58,7 @@ import java.nio.file.Path;
import java.io.File;
import org.apache.commons.lang3.StringUtils;
+import org.fife.ui.autocomplete.AutoCompletion;
import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit;
import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
@@ -65,7 +66,7 @@ import org.fife.ui.rtextarea.Gutter;
import org.fife.ui.rtextarea.RTextScrollPane;
import cc.arduino.UpdatableBoardsLibsFakeURLsHandler;
-import cc.arduino.autocomplete.FakeCompletionProvider;
+import cc.arduino.autocomplete.ClangCompletionProvider;
import processing.app.helpers.DocumentTextChangeListener;
import processing.app.syntax.ArduinoTokenMakerFactory;
import processing.app.syntax.PdeKeywords;
@@ -120,7 +121,17 @@ public class EditorTab extends JPanel implements SketchFile.TextStorage {
applyPreferences();
add(scrollPane, BorderLayout.CENTER);
editor.base.addEditorFontResizeMouseWheelListener(textarea);
- textarea.setupAutoComplete(file.getSketch(), new FakeCompletionProvider());
+// SketchCompletionProvider completionProvider = new SketchCompletionProvider(
+// editor.getSketch(), textarea, new ClangCompletionProvider(editor));
+
+ AutoCompletion ac = new AutoCompletion(new ClangCompletionProvider(editor));
+ ac.setAutoActivationEnabled(true);
+ ac.setShowDescWindow(false);
+ ac.setAutoCompleteSingleChoices(true);
+ ac.setParameterAssistanceEnabled(true);
+ // ac.setParamChoicesRenderer(new CompletionsRenderer());
+ // ac.setListCellRenderer(new CompletionsRenderer());
+ ac.install(textarea);
}
private RSyntaxDocument createDocument(String contents) {
diff --git a/app/src/processing/app/SketchController.java b/app/src/processing/app/SketchController.java
index ce9e468cc..f4cbad0e2 100644
--- a/app/src/processing/app/SketchController.java
+++ b/app/src/processing/app/SketchController.java
@@ -680,6 +680,40 @@ public class SketchController {
return Paths.get(tempFolder.getAbsolutePath(), sketch.getPrimaryFile().getFileName()).toFile();
}
+ /**
+ * Preprocess sketch and obtain code-completions.
+ *
+ * @return null if compilation failed, main class name if not
+ */
+ public String codeComplete(SketchFile file, int line, int col) throws RunnerException, PreferencesMapException, IOException {
+ // run the preprocessor
+ for (CompilerProgressListener progressListener : editor.status.getCompilerProgressListeners()){
+ progressListener.progress(20);
+ }
+
+ ensureExistence();
+
+ boolean deleteTemp = false;
+ File pathToSketch = sketch.getPrimaryFile().getFile();
+ File requestedFile = file.getFile();
+ if (sketch.isModified()) {
+ // If any files are modified, make a copy of the sketch with the changes
+ // saved, so arduino-builder will see the modifications.
+ pathToSketch = saveSketchInTempFolder();
+ // This takes into account when the sketch is copied into a temporary folder
+ requestedFile = new File(pathToSketch.getParent(), requestedFile.getName());
+ deleteTemp = true;
+ }
+
+ try {
+ return new Compiler(pathToSketch, sketch).codeComplete(editor.status.getCompilerProgressListeners(), requestedFile, line, col);
+ } finally {
+ // Make sure we clean up any temporary sketch copy
+ if (deleteTemp)
+ FileUtils.recursiveDelete(pathToSketch.getParentFile());
+ }
+ }
+
/**
* Handle export to applet.
*/
diff --git a/app/src/processing/app/syntax/SketchTextArea.java b/app/src/processing/app/syntax/SketchTextArea.java
index 95a5ec7ab..060409ba5 100644
--- a/app/src/processing/app/syntax/SketchTextArea.java
+++ b/app/src/processing/app/syntax/SketchTextArea.java
@@ -135,22 +135,6 @@ public class SketchTextArea extends RSyntaxTextArea {
setLinkGenerator(new DocLinkGenerator(pdeKeywords));
}
- public void setupAutoComplete(Sketch sketch, CompletionProvider provider) {
-
- SketchCompletionProvider completionProvider = new SketchCompletionProvider(sketch, this, provider);
-
- AutoCompletion ac = new AutoCompletion( completionProvider );
-
- ac.setAutoActivationEnabled(true);
- ac.setShowDescWindow(false);
- ac.setAutoCompleteSingleChoices(true);
- ac.setParameterAssistanceEnabled(true);
-// ac.setParamChoicesRenderer(new CompletionsRenderer());
-// ac.setListCellRenderer(new CompletionsRenderer());
- ac.install(this);
-
- }
-
private void installFeatures() throws IOException {
setTheme(PreferencesData.get("editor.syntax_theme", "default"));
diff --git a/arduino-core/src/cc/arduino/Compiler.java b/arduino-core/src/cc/arduino/Compiler.java
index c2c5b0ff6..0b77cd3ed 100644
--- a/arduino-core/src/cc/arduino/Compiler.java
+++ b/arduino-core/src/cc/arduino/Compiler.java
@@ -125,7 +125,7 @@ public class Compiler implements MessageConsumer {
}
enum BuilderAction {
- COMPILE("-compile"), DUMP_PREFS("-dump-prefs");
+ COMPILE("-compile"), DUMP_PREFS("-dump-prefs"), CODE_COMPLETE("-code-complete-at");
final String value;
@@ -143,6 +143,10 @@ public class Compiler implements MessageConsumer {
private final boolean verbose;
private RunnerException exception;
+ private File codeCompleteFile;
+ private int codeCompleteLine;
+ private int codeCompleteCol;
+
public Compiler(Sketch data) {
this(data.getPrimaryFile().getFile(), data);
}
@@ -193,6 +197,34 @@ public class Compiler implements MessageConsumer {
return sketch.getPrimaryFile().getFileName();
}
+ public String codeComplete(ArrayList progListeners, File file, int line, int col) throws RunnerException, PreferencesMapException, IOException {
+ this.buildPath = sketch.getBuildPath().getAbsolutePath();
+ this.buildCache = BaseNoGui.getCachePath();
+
+ TargetBoard board = BaseNoGui.getTargetBoard();
+ if (board == null) {
+ throw new RunnerException("Board is not selected");
+ }
+
+ TargetPlatform platform = board.getContainerPlatform();
+ TargetPackage aPackage = platform.getContainerPackage();
+ String vidpid = VIDPID();
+
+ ByteArrayOutputStream completions = new ByteArrayOutputStream();
+ MessageConsumerOutputStream out = new MessageConsumerOutputStream(new ProgressAwareMessageConsumer(new I18NAwareMessageConsumer(new PrintStream(completions), System.err), progListeners), "\n");
+ MessageConsumerOutputStream err = new MessageConsumerOutputStream(new I18NAwareMessageConsumer(System.err, Compiler.this), "\n");
+
+ codeCompleteFile = file;
+ codeCompleteLine = line;
+ codeCompleteCol = col;
+ callArduinoBuilder(board, platform, aPackage, vidpid, BuilderAction.CODE_COMPLETE, out, err);
+
+ out.flush();
+ err.flush();
+
+ return completions.toString();
+ }
+
private String VIDPID() {
BoardPort boardPort = BaseNoGui.getDiscoveryManager().find(PreferencesData.get("serial.port"));
if (boardPort == null) {
@@ -234,6 +266,9 @@ public class Compiler implements MessageConsumer {
List cmd = new ArrayList<>();
cmd.add(BaseNoGui.getContentFile("arduino-builder").getAbsolutePath());
cmd.add(action.value);
+ if (action == BuilderAction.CODE_COMPLETE) {
+ cmd.add(codeCompleteFile.getAbsolutePath() + ":" + codeCompleteLine + ":" + codeCompleteCol);
+ }
cmd.add("-logger=machine");
File installedPackagesFolder = new File(BaseNoGui.getSettingsFolder(), "packages");
@@ -280,9 +315,7 @@ public class Compiler implements MessageConsumer {
}
}
- //commandLine.addArgument("-debug-level=10", false);
-
- if (verbose) {
+ if (verbose && action != BuilderAction.CODE_COMPLETE) {
cmd.add("-verbose");
}