1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-02-26 20:54:22 +01:00

Testing autocomplete with arduino-preprocessor

This commit is contained in:
Cristian Maglie 2017-05-15 17:40:23 +02:00 committed by Martino Facchin
parent ff17c8667f
commit 42930e22b0
8 changed files with 235 additions and 23 deletions

View File

@ -55,5 +55,6 @@
<classpathentry kind="lib" path="lib/jtouchbar-1.0.0.jar"/> <classpathentry kind="lib" path="lib/jtouchbar-1.0.0.jar"/>
<classpathentry kind="lib" path="lib/commons-lang3-3.8.1.jar"/> <classpathentry kind="lib" path="lib/commons-lang3-3.8.1.jar"/>
<classpathentry kind="lib" path="lib/jssc-2.8.0-arduino4.jar"/> <classpathentry kind="lib" path="lib/jssc-2.8.0-arduino4.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/AutoComplete"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@ -0,0 +1,61 @@
package cc.arduino.autocomplete;
import java.util.ArrayList;
import java.util.List;
public class ArduinoCompletionsList extends ArrayList<ArduinoCompletion> {
}
class ArduinoCompletion {
ArduinoCompletionDetail completion;
String type;
public ArduinoCompletionDetail getCompletion() {
return completion;
}
public String getType() {
return type;
}
}
class ArduinoCompletionDetail {
List<CompletionChunk> chunks;
String brief;
public List<CompletionChunk> 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;
}
}

View File

@ -7,7 +7,7 @@ import org.fife.ui.autocomplete.DefaultCompletionProvider;
* @author Ricardo JL Rufino (ricardo@criativasoft.com.br) * @author Ricardo JL Rufino (ricardo@criativasoft.com.br)
* @date 28/04/2017 * @date 28/04/2017
*/ */
public class BaseCCompletionProvider extends DefaultCompletionProvider{ public class BaseCCompletionProvider extends DefaultCompletionProvider {
@Override @Override
protected boolean isValidChar(char ch) { protected boolean isValidChar(char ch) {

View File

@ -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<Completion> getCompletionByInputText(String inputText) {
System.out.println("INPUTTEXT: " + inputText);
return super.getCompletionByInputText(inputText);
}
@Override
protected List<Completion> 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<Completion> 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;
}
}

View File

@ -58,6 +58,7 @@ import java.nio.file.Path;
import java.io.File; import java.io.File;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.fife.ui.autocomplete.AutoCompletion;
import org.fife.ui.rsyntaxtextarea.RSyntaxDocument; import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit; import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit;
import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities; import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
@ -65,7 +66,7 @@ import org.fife.ui.rtextarea.Gutter;
import org.fife.ui.rtextarea.RTextScrollPane; import org.fife.ui.rtextarea.RTextScrollPane;
import cc.arduino.UpdatableBoardsLibsFakeURLsHandler; import cc.arduino.UpdatableBoardsLibsFakeURLsHandler;
import cc.arduino.autocomplete.FakeCompletionProvider; import cc.arduino.autocomplete.ClangCompletionProvider;
import processing.app.helpers.DocumentTextChangeListener; import processing.app.helpers.DocumentTextChangeListener;
import processing.app.syntax.ArduinoTokenMakerFactory; import processing.app.syntax.ArduinoTokenMakerFactory;
import processing.app.syntax.PdeKeywords; import processing.app.syntax.PdeKeywords;
@ -120,7 +121,17 @@ public class EditorTab extends JPanel implements SketchFile.TextStorage {
applyPreferences(); applyPreferences();
add(scrollPane, BorderLayout.CENTER); add(scrollPane, BorderLayout.CENTER);
editor.base.addEditorFontResizeMouseWheelListener(textarea); 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) { private RSyntaxDocument createDocument(String contents) {

View File

@ -680,6 +680,40 @@ public class SketchController {
return Paths.get(tempFolder.getAbsolutePath(), sketch.getPrimaryFile().getFileName()).toFile(); 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. * Handle export to applet.
*/ */

View File

@ -135,22 +135,6 @@ public class SketchTextArea extends RSyntaxTextArea {
setLinkGenerator(new DocLinkGenerator(pdeKeywords)); 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 { private void installFeatures() throws IOException {
setTheme(PreferencesData.get("editor.syntax_theme", "default")); setTheme(PreferencesData.get("editor.syntax_theme", "default"));

View File

@ -125,7 +125,7 @@ public class Compiler implements MessageConsumer {
} }
enum BuilderAction { enum BuilderAction {
COMPILE("-compile"), DUMP_PREFS("-dump-prefs"); COMPILE("-compile"), DUMP_PREFS("-dump-prefs"), CODE_COMPLETE("-code-complete-at");
final String value; final String value;
@ -143,6 +143,10 @@ public class Compiler implements MessageConsumer {
private final boolean verbose; private final boolean verbose;
private RunnerException exception; private RunnerException exception;
private File codeCompleteFile;
private int codeCompleteLine;
private int codeCompleteCol;
public Compiler(Sketch data) { public Compiler(Sketch data) {
this(data.getPrimaryFile().getFile(), data); this(data.getPrimaryFile().getFile(), data);
} }
@ -193,6 +197,34 @@ public class Compiler implements MessageConsumer {
return sketch.getPrimaryFile().getFileName(); return sketch.getPrimaryFile().getFileName();
} }
public String codeComplete(ArrayList<CompilerProgressListener> 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() { private String VIDPID() {
BoardPort boardPort = BaseNoGui.getDiscoveryManager().find(PreferencesData.get("serial.port")); BoardPort boardPort = BaseNoGui.getDiscoveryManager().find(PreferencesData.get("serial.port"));
if (boardPort == null) { if (boardPort == null) {
@ -234,6 +266,9 @@ public class Compiler implements MessageConsumer {
List<String> cmd = new ArrayList<>(); List<String> cmd = new ArrayList<>();
cmd.add(BaseNoGui.getContentFile("arduino-builder").getAbsolutePath()); cmd.add(BaseNoGui.getContentFile("arduino-builder").getAbsolutePath());
cmd.add(action.value); cmd.add(action.value);
if (action == BuilderAction.CODE_COMPLETE) {
cmd.add(codeCompleteFile.getAbsolutePath() + ":" + codeCompleteLine + ":" + codeCompleteCol);
}
cmd.add("-logger=machine"); cmd.add("-logger=machine");
File installedPackagesFolder = new File(BaseNoGui.getSettingsFolder(), "packages"); File installedPackagesFolder = new File(BaseNoGui.getSettingsFolder(), "packages");
@ -280,9 +315,7 @@ public class Compiler implements MessageConsumer {
} }
} }
//commandLine.addArgument("-debug-level=10", false); if (verbose && action != BuilderAction.CODE_COMPLETE) {
if (verbose) {
cmd.add("-verbose"); cmd.add("-verbose");
} }