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:
parent
ff17c8667f
commit
42930e22b0
@ -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>
|
||||||
|
61
app/src/cc/arduino/autocomplete/ArduinoCompletionsList.java
Normal file
61
app/src/cc/arduino/autocomplete/ArduinoCompletionsList.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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) {
|
||||||
|
88
app/src/cc/arduino/autocomplete/ClangCompletionProvider.java
Normal file
88
app/src/cc/arduino/autocomplete/ClangCompletionProvider.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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) {
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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"));
|
||||||
|
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user