mirror of
https://github.com/arduino/Arduino.git
synced 2024-11-29 10:24:12 +01:00
Make Compiler independent from Sketch.
Create a class SketchData to store all relevant data for a sketch (trying to keep GUI stuff out of the way). Moved preprocessing code from Sketch to Compiler.
This commit is contained in:
parent
e6563cfebf
commit
79ab98fef9
@ -105,7 +105,7 @@ public class Base {
|
||||
static private LibraryList libraries;
|
||||
|
||||
// maps #included files to their library folder
|
||||
static Map<String, Library> importToLibraryTable;
|
||||
public static Map<String, Library> importToLibraryTable;
|
||||
|
||||
// classpath for all known libraries for p5
|
||||
// (both those in the p5/libs folder and those with lib subfolders
|
||||
|
@ -29,13 +29,11 @@ import cc.arduino.packages.UploaderAndMonitorFactory;
|
||||
import cc.arduino.packages.Uploader;
|
||||
import processing.app.debug.*;
|
||||
import processing.app.debug.Compiler;
|
||||
import processing.app.debug.Compiler.ProgressListener;
|
||||
import processing.app.forms.PasswordAuthorizationDialog;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
import processing.app.helpers.FileUtils;
|
||||
import processing.app.packages.Library;
|
||||
import processing.app.packages.LibraryList;
|
||||
import processing.app.preproc.*;
|
||||
import processing.core.*;
|
||||
import static processing.app.I18n._;
|
||||
|
||||
import java.io.*;
|
||||
@ -55,12 +53,6 @@ public class Sketch {
|
||||
/** main pde file for this sketch. */
|
||||
private File primaryFile;
|
||||
|
||||
/**
|
||||
* Name of sketch, which is the name of main file
|
||||
* (without .pde or .java extension)
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/** true if any of the files have been modified. */
|
||||
private boolean modified;
|
||||
|
||||
@ -77,25 +69,10 @@ public class Sketch {
|
||||
private SketchCodeDocument currentCodeDoc;
|
||||
private int currentIndex;
|
||||
|
||||
/**
|
||||
* Number of sketchCode objects (tabs) in the current sketch. Note that this
|
||||
* will be the same as code.length, because the getCode() method returns
|
||||
* just the code[] array, rather than a copy of it, or an array that's been
|
||||
* resized to just the relevant files themselves.
|
||||
* http://dev.processing.org/bugs/show_bug.cgi?id=940
|
||||
*/
|
||||
private int codeCount;
|
||||
private SketchCodeDocument[] codeDocs;
|
||||
private SketchData data;
|
||||
|
||||
/** Class name for the PApplet, as determined by the preprocessor. */
|
||||
private String appletClassName;
|
||||
/** Class path determined during build. */
|
||||
private String classPath;
|
||||
|
||||
/**
|
||||
* List of library folders.
|
||||
*/
|
||||
private LibraryList importedLibraries;
|
||||
|
||||
/**
|
||||
* File inside the build directory that contains the build options
|
||||
@ -107,16 +84,16 @@ public class Sketch {
|
||||
* path is location of the main .pde file, because this is also
|
||||
* simplest to use when opening the file from the finder/explorer.
|
||||
*/
|
||||
public Sketch(Editor editor, File file) throws IOException {
|
||||
this.editor = editor;
|
||||
|
||||
public Sketch(Editor _editor, File file) throws IOException {
|
||||
editor = _editor;
|
||||
data = new SketchData();
|
||||
primaryFile = file;
|
||||
|
||||
// get the name of the sketch by chopping .pde or .java
|
||||
// off of the main file name
|
||||
String mainFilename = primaryFile.getName();
|
||||
int suffixLength = getDefaultExtension().length() + 1;
|
||||
name = mainFilename.substring(0, mainFilename.length() - suffixLength);
|
||||
data.setName(mainFilename.substring(0, mainFilename.length() - suffixLength));
|
||||
|
||||
// lib/build must exist when the application is started
|
||||
// it is added to the CLASSPATH by default, but if it doesn't
|
||||
@ -167,9 +144,7 @@ public class Sketch {
|
||||
|
||||
// reset these because load() may be called after an
|
||||
// external editor event. (fix for 0099)
|
||||
codeCount = 0;
|
||||
|
||||
codeDocs = new SketchCodeDocument[list.length];
|
||||
data.clearCodeDocs();
|
||||
|
||||
List<String> extensions = getExtensions();
|
||||
|
||||
@ -192,8 +167,7 @@ public class Sketch {
|
||||
// Don't allow people to use files with invalid names, since on load,
|
||||
// it would be otherwise possible to sneak in nasty filenames. [0116]
|
||||
if (Sketch.isSanitaryName(base)) {
|
||||
codeDocs[codeCount++] =
|
||||
new SketchCodeDocument(new File(folder, filename));
|
||||
data.addCodeDoc(new SketchCodeDocument(new File(folder, filename)));
|
||||
} else {
|
||||
System.err.println(I18n.format("File name {0} is invalid: ignored", filename));
|
||||
}
|
||||
@ -201,26 +175,21 @@ public class Sketch {
|
||||
}
|
||||
}
|
||||
|
||||
if (codeCount == 0)
|
||||
if (data.getCodeCount() == 0)
|
||||
throw new IOException(_("No valid code files found"));
|
||||
|
||||
// Remove any code that wasn't proper
|
||||
codeDocs = (SketchCodeDocument[]) PApplet.subset(codeDocs, 0, codeCount);
|
||||
|
||||
// move the main class to the first tab
|
||||
// start at 1, if it's at zero, don't bother
|
||||
for (int i = 1; i < codeCount; i++) {
|
||||
for (SketchCodeDocument codeDoc : data.getCodeDocs()) {
|
||||
//if (code[i].file.getName().equals(mainFilename)) {
|
||||
if (codeDocs[i].getCode().getFile().equals(primaryFile)) {
|
||||
SketchCodeDocument temp = codeDocs[0];
|
||||
codeDocs[0] = codeDocs[i];
|
||||
codeDocs[i] = temp;
|
||||
if (codeDoc.getCode().getFile().equals(primaryFile)) {
|
||||
data.moveCodeDocToFront(codeDoc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// sort the entries at the top
|
||||
sortCode();
|
||||
data.sortCode();
|
||||
|
||||
// set the main file to be the current tab
|
||||
if (editor != null) {
|
||||
@ -229,47 +198,6 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
protected void replaceCode(SketchCode newCode) {
|
||||
for (int i = 0; i < codeCount; i++) {
|
||||
if (codeDocs[i].getCode().getFileName().equals(newCode.getFileName())) {
|
||||
codeDocs[i].setCode(newCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void insertCode(SketchCode newCode) {
|
||||
// make sure the user didn't hide the sketch folder
|
||||
ensureExistence();
|
||||
|
||||
// add file to the code/codeCount list, resort the list
|
||||
//if (codeCount == code.length) {
|
||||
codeDocs = (SketchCodeDocument[]) PApplet.append(codeDocs, newCode);
|
||||
codeCount++;
|
||||
//}
|
||||
//code[codeCount++] = newCode;
|
||||
}
|
||||
|
||||
|
||||
protected void sortCode() {
|
||||
// cheap-ass sort of the rest of the files
|
||||
// it's a dumb, slow sort, but there shouldn't be more than ~5 files
|
||||
for (int i = 1; i < codeCount; i++) {
|
||||
int who = i;
|
||||
for (int j = i + 1; j < codeCount; j++) {
|
||||
if (codeDocs[j].getCode().getFileName().compareTo(codeDocs[who].getCode().getFileName()) < 0) {
|
||||
who = j; // this guy is earlier in the alphabet
|
||||
}
|
||||
}
|
||||
if (who != i) { // swap with someone if changes made
|
||||
SketchCodeDocument temp = codeDocs[who];
|
||||
codeDocs[who] = codeDocs[i];
|
||||
codeDocs[i] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean renamingCode;
|
||||
|
||||
/**
|
||||
@ -380,7 +308,7 @@ public class Sketch {
|
||||
// Don't let the user create the main tab as a .java file instead of .pde
|
||||
if (!isDefaultExtension(newExtension)) {
|
||||
if (renamingCode) { // If creating a new tab, don't show this error
|
||||
if (current == codeDocs[0].getCode()) { // If this is the main tab, disallow
|
||||
if (current == data.getCodeDoc(0).getCode()) { // If this is the main tab, disallow
|
||||
Base.showWarning(_("Problem with rename"),
|
||||
_("The main file can't use an extension.\n" +
|
||||
"(It may be time for your to graduate to a\n" +
|
||||
@ -402,7 +330,7 @@ public class Sketch {
|
||||
// In Arduino, we want to allow files with the same name but different
|
||||
// extensions, so compare the full names (including extensions). This
|
||||
// might cause problems: http://dev.processing.org/bugs/show_bug.cgi?id=543
|
||||
for (SketchCodeDocument c : codeDocs) {
|
||||
for (SketchCodeDocument c : data.getCodeDocs()) {
|
||||
if (newName.equalsIgnoreCase(c.getCode().getFileName())) {
|
||||
Base.showMessage(_("Nope"),
|
||||
I18n.format(
|
||||
@ -424,9 +352,9 @@ public class Sketch {
|
||||
}
|
||||
|
||||
if (renamingCode && currentIndex == 0) {
|
||||
for (int i = 1; i < codeCount; i++) {
|
||||
if (sanitaryName.equalsIgnoreCase(codeDocs[i].getCode().getPrettyName()) &&
|
||||
codeDocs[i].getCode().isExtension("cpp")) {
|
||||
for (SketchCodeDocument codeDoc : data.getCodeDocs()) {
|
||||
if (sanitaryName.equalsIgnoreCase(codeDoc.getCode().getPrettyName()) &&
|
||||
codeDoc.getCode().isExtension("cpp")) {
|
||||
Base.showMessage(_("Nope"),
|
||||
I18n.format(
|
||||
_("You can't rename the sketch to \"{0}\"\n" +
|
||||
@ -500,8 +428,8 @@ public class Sketch {
|
||||
|
||||
// save each of the other tabs because this is gonna be re-opened
|
||||
try {
|
||||
for (int i = 1; i < codeCount; i++) {
|
||||
codeDocs[i].getCode().save();
|
||||
for (SketchCodeDocument codeDoc : data.getCodeDocs()) {
|
||||
codeDoc.getCode().save();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Base.showWarning(_("Error"), _("Could not rename the sketch. (1)"), e);
|
||||
@ -560,11 +488,12 @@ public class Sketch {
|
||||
}
|
||||
SketchCode newCode = new SketchCode(newFile);
|
||||
//System.out.println("new code is named " + newCode.getPrettyName() + " " + newCode.getFile());
|
||||
insertCode(newCode);
|
||||
ensureExistence();
|
||||
data.insertCode(newCode);
|
||||
}
|
||||
|
||||
// sort the entries
|
||||
sortCode();
|
||||
data.sortCode();
|
||||
|
||||
// set the new guy as current
|
||||
setCurrentCode(newName);
|
||||
@ -629,7 +558,7 @@ public class Sketch {
|
||||
}
|
||||
|
||||
// remove code from the list
|
||||
removeCode(current);
|
||||
data.removeCode(current);
|
||||
|
||||
// just set current tab to the main tab
|
||||
setCurrentCode(0);
|
||||
@ -641,29 +570,12 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
protected void removeCode(SketchCode which) {
|
||||
// remove it from the internal list of files
|
||||
// resort internal list of files
|
||||
for (int i = 0; i < codeCount; i++) {
|
||||
if (codeDocs[i].getCode() == which) {
|
||||
for (int j = i; j < codeCount-1; j++) {
|
||||
codeDocs[j] = codeDocs[j+1];
|
||||
}
|
||||
codeCount--;
|
||||
codeDocs = (SketchCodeDocument[]) PApplet.shorten(codeDocs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
System.err.println(_("removeCode: internal error.. could not find code"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Move to the previous tab.
|
||||
*/
|
||||
public void handlePrevCode() {
|
||||
int prev = currentIndex - 1;
|
||||
if (prev < 0) prev = codeCount-1;
|
||||
if (prev < 0) prev = data.getCodeCount()-1;
|
||||
setCurrentCode(prev);
|
||||
}
|
||||
|
||||
@ -672,7 +584,7 @@ public class Sketch {
|
||||
* Move to the next tab.
|
||||
*/
|
||||
public void handleNextCode() {
|
||||
setCurrentCode((currentIndex + 1) % codeCount);
|
||||
setCurrentCode((currentIndex + 1) % data.getCodeCount());
|
||||
}
|
||||
|
||||
|
||||
@ -689,8 +601,8 @@ public class Sketch {
|
||||
|
||||
protected void calcModified() {
|
||||
modified = false;
|
||||
for (int i = 0; i < codeCount; i++) {
|
||||
if (codeDocs[i].getCode().isModified()) {
|
||||
for (SketchCodeDocument codeDoc : data.getCodeDocs()) {
|
||||
if (codeDoc.getCode().isModified()) {
|
||||
modified = true;
|
||||
break;
|
||||
}
|
||||
@ -773,9 +685,9 @@ public class Sketch {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < codeCount; i++) {
|
||||
if (codeDocs[i].getCode().isModified())
|
||||
codeDocs[i].getCode().save();
|
||||
for (SketchCodeDocument codeDoc : data.getCodeDocs()) {
|
||||
if (codeDoc.getCode().isModified())
|
||||
codeDoc.getCode().save();
|
||||
}
|
||||
calcModified();
|
||||
return true;
|
||||
@ -783,7 +695,7 @@ public class Sketch {
|
||||
|
||||
|
||||
protected boolean renameCodeToInoExtension(File pdeFile) {
|
||||
for (SketchCodeDocument c : codeDocs) {
|
||||
for (SketchCodeDocument c : data.getCodeDocs()) {
|
||||
if (!c.getCode().getFile().equals(pdeFile))
|
||||
continue;
|
||||
|
||||
@ -834,9 +746,9 @@ public class Sketch {
|
||||
// make sure there doesn't exist a .cpp file with that name already
|
||||
// but ignore this situation for the first tab, since it's probably being
|
||||
// resaved (with the same name) to another location/folder.
|
||||
for (int i = 1; i < codeCount; i++) {
|
||||
if (newName.equalsIgnoreCase(codeDocs[i].getCode().getPrettyName()) &&
|
||||
codeDocs[i].getCode().isExtension("cpp")) {
|
||||
for (SketchCodeDocument codeDoc : data.getCodeDocs()) {
|
||||
if (newName.equalsIgnoreCase(codeDoc.getCode().getPrettyName()) &&
|
||||
codeDoc.getCode().isExtension("cpp")) {
|
||||
Base.showMessage(_("Nope"),
|
||||
I18n.format(
|
||||
_("You can't save the sketch as \"{0}\"\n" +
|
||||
@ -886,9 +798,10 @@ public class Sketch {
|
||||
}
|
||||
|
||||
// save the other tabs to their new location
|
||||
for (int i = 1; i < codeCount; i++) {
|
||||
File newFile = new File(newFolder, codeDocs[i].getCode().getFileName());
|
||||
codeDocs[i].getCode().saveAs(newFile);
|
||||
for (SketchCodeDocument codeDoc : data.getCodeDocs()) {
|
||||
if (data.indexOfCodeDoc(codeDoc) == 0) continue;
|
||||
File newFile = new File(newFolder, codeDoc.getCode().getFileName());
|
||||
codeDoc.getCode().saveAs(newFile);
|
||||
}
|
||||
|
||||
// re-copy the data folder (this may take a while.. add progress bar?)
|
||||
@ -913,7 +826,7 @@ public class Sketch {
|
||||
|
||||
// save the main tab with its new name
|
||||
File newFile = new File(newFolder, newName + ".ino");
|
||||
codeDocs[0].getCode().saveAs(newFile);
|
||||
data.getCodeDoc(0).getCode().saveAs(newFile);
|
||||
|
||||
editor.handleOpenUnchecked(newFile,
|
||||
currentIndex,
|
||||
@ -1079,11 +992,12 @@ public class Sketch {
|
||||
SketchCode newCode = new SketchCode(destFile);
|
||||
|
||||
if (replacement) {
|
||||
replaceCode(newCode);
|
||||
data.replaceCode(newCode);
|
||||
|
||||
} else {
|
||||
insertCode(newCode);
|
||||
sortCode();
|
||||
ensureExistence();
|
||||
data.insertCode(newCode);
|
||||
data.sortCode();
|
||||
}
|
||||
setCurrentCode(filename);
|
||||
editor.header.repaint();
|
||||
@ -1096,7 +1010,7 @@ public class Sketch {
|
||||
if (editor.untitled) { // TODO probably not necessary? problematic?
|
||||
// If a file has been added, mark the main code as modified so
|
||||
// that the sketch is properly saved.
|
||||
codeDocs[0].getCode().setModified(true);
|
||||
data.getCodeDoc(0).getCode().setModified(true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -1162,7 +1076,7 @@ public class Sketch {
|
||||
currentCodeDoc.setScrollPosition(editor.getScrollPosition());
|
||||
}
|
||||
|
||||
currentCodeDoc = codeDocs[which];
|
||||
currentCodeDoc = data.getCodeDoc(which);
|
||||
current = currentCodeDoc.getCode();
|
||||
currentIndex = which;
|
||||
|
||||
@ -1177,10 +1091,10 @@ public class Sketch {
|
||||
* @param findName the file name (not pretty name) to be shown
|
||||
*/
|
||||
protected void setCurrentCode(String findName) {
|
||||
for (int i = 0; i < codeCount; i++) {
|
||||
if (findName.equals(codeDocs[i].getCode().getFileName()) ||
|
||||
findName.equals(codeDocs[i].getCode().getPrettyName())) {
|
||||
setCurrentCode(i);
|
||||
for (SketchCodeDocument codeDoc : data.getCodeDocs()) {
|
||||
if (findName.equals(codeDoc.getCode().getFileName()) ||
|
||||
findName.equals(codeDoc.getCode().getPrettyName())) {
|
||||
setCurrentCode(data.indexOfCodeDoc(codeDoc));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1290,144 +1204,6 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build all the code for this sketch.
|
||||
*
|
||||
* In an advanced program, the returned class name could be different,
|
||||
* which is why the className is set based on the return value.
|
||||
* A compilation error will burp up a RunnerException.
|
||||
*
|
||||
* Setting purty to 'true' will cause exception line numbers to be incorrect.
|
||||
* Unless you know the code compiles, you should first run the preprocessor
|
||||
* with purty set to false to make sure there are no errors, then once
|
||||
* successful, re-export with purty set to true.
|
||||
*
|
||||
* @param buildPath Location to copy all the .java files
|
||||
* @return null if compilation failed, main class name if not
|
||||
*/
|
||||
public void preprocess(String buildPath) throws RunnerException {
|
||||
preprocess(buildPath, new PdePreprocessor());
|
||||
}
|
||||
|
||||
public void preprocess(String buildPath, PdePreprocessor preprocessor) throws RunnerException {
|
||||
// make sure the user didn't hide the sketch folder
|
||||
ensureExistence();
|
||||
|
||||
classPath = buildPath;
|
||||
|
||||
// // figure out the contents of the code folder to see if there
|
||||
// // are files that need to be added to the imports
|
||||
// if (codeFolder.exists()) {
|
||||
// libraryPath = codeFolder.getAbsolutePath();
|
||||
//
|
||||
// // get a list of .jar files in the "code" folder
|
||||
// // (class files in subfolders should also be picked up)
|
||||
// String codeFolderClassPath =
|
||||
// Compiler.contentsToClassPath(codeFolder);
|
||||
// // append the jar files in the code folder to the class path
|
||||
// classPath += File.pathSeparator + codeFolderClassPath;
|
||||
// // get list of packages found in those jars
|
||||
// codeFolderPackages =
|
||||
// Compiler.packageListFromClassPath(codeFolderClassPath);
|
||||
//
|
||||
// } else {
|
||||
// libraryPath = "";
|
||||
// }
|
||||
|
||||
// 1. concatenate all .pde files to the 'main' pde
|
||||
// store line number for starting point of each code bit
|
||||
|
||||
StringBuffer bigCode = new StringBuffer();
|
||||
int bigCount = 0;
|
||||
for (SketchCodeDocument scd : codeDocs) {
|
||||
SketchCode sc = scd.getCode();
|
||||
if (sc.isExtension("ino") || sc.isExtension("pde")) {
|
||||
sc.setPreprocOffset(bigCount);
|
||||
// These #line directives help the compiler report errors with
|
||||
// correct the filename and line number (issue 281 & 907)
|
||||
bigCode.append("#line 1 \"" + sc.getFileName() + "\"\n");
|
||||
bigCode.append(sc.getProgram());
|
||||
bigCode.append('\n');
|
||||
bigCount += sc.getLineCount();
|
||||
}
|
||||
}
|
||||
|
||||
// Note that the headerOffset isn't applied until compile and run, because
|
||||
// it only applies to the code after it's been written to the .java file.
|
||||
int headerOffset = 0;
|
||||
try {
|
||||
headerOffset = preprocessor.writePrefix(bigCode.toString());
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
fnfe.printStackTrace();
|
||||
String msg = _("Build folder disappeared or could not be written");
|
||||
throw new RunnerException(msg);
|
||||
}
|
||||
|
||||
// 2. run preproc on that code using the sugg class name
|
||||
// to create a single .java file and write to buildpath
|
||||
|
||||
try {
|
||||
// Output file
|
||||
File streamFile = new File(buildPath, name + ".cpp");
|
||||
FileOutputStream outputStream = new FileOutputStream(streamFile);
|
||||
preprocessor.write(outputStream);
|
||||
outputStream.close();
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
fnfe.printStackTrace();
|
||||
String msg = _("Build folder disappeared or could not be written");
|
||||
throw new RunnerException(msg);
|
||||
} catch (RunnerException pe) {
|
||||
// RunnerExceptions are caught here and re-thrown, so that they don't
|
||||
// get lost in the more general "Exception" handler below.
|
||||
throw pe;
|
||||
|
||||
} catch (Exception ex) {
|
||||
// TODO better method for handling this?
|
||||
System.err.println(I18n.format(_("Uncaught exception type: {0}"), ex.getClass()));
|
||||
ex.printStackTrace();
|
||||
throw new RunnerException(ex.toString());
|
||||
}
|
||||
|
||||
// grab the imports from the code just preproc'd
|
||||
|
||||
importedLibraries = new LibraryList();
|
||||
for (String item : preprocessor.getExtraImports()) {
|
||||
Library lib = Base.importToLibraryTable.get(item);
|
||||
if (lib != null && !importedLibraries.contains(lib)) {
|
||||
importedLibraries.add(lib);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. then loop over the code[] and save each .java file
|
||||
|
||||
for (SketchCodeDocument scd : codeDocs) {
|
||||
SketchCode sc = scd.getCode();
|
||||
if (sc.isExtension("c") || sc.isExtension("cpp") || sc.isExtension("h")) {
|
||||
// no pre-processing services necessary for java files
|
||||
// just write the the contents of 'program' to a .java file
|
||||
// into the build directory. uses byte stream and reader/writer
|
||||
// shtuff so that unicode bunk is properly handled
|
||||
String filename = sc.getFileName(); //code[i].name + ".java";
|
||||
try {
|
||||
Base.saveFile(sc.getProgram(), new File(buildPath, filename));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RunnerException(I18n.format(_("Problem moving {0} to the build folder"), filename));
|
||||
}
|
||||
// sc.setPreprocName(filename);
|
||||
|
||||
} else if (sc.isExtension("ino") || sc.isExtension("pde")) {
|
||||
// The compiler and runner will need this to have a proper offset
|
||||
sc.addPreprocOffset(headerOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public LibraryList getImportedLibraries() {
|
||||
return importedLibraries;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map an error from a set of processed .java files back to its location
|
||||
@ -1479,31 +1255,6 @@ public class Sketch {
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Map an error from a set of processed .java files back to its location
|
||||
* in the actual sketch.
|
||||
* @param message The error message.
|
||||
* @param dotJavaFilename The .java file where the exception was found.
|
||||
* @param dotJavaLine Line number of the .java file for the exception (0-indexed!)
|
||||
* @return A RunnerException to be sent to the editor, or null if it wasn't
|
||||
* possible to place the exception to the sketch code.
|
||||
*/
|
||||
public RunnerException placeException(String message,
|
||||
String dotJavaFilename,
|
||||
int dotJavaLine) {
|
||||
// Placing errors is simple, because we inserted #line directives
|
||||
// into the preprocessed source. The compiler gives us correct
|
||||
// the file name and line number. :-)
|
||||
for (int codeIndex = 0; codeIndex < getCodeCount(); codeIndex++) {
|
||||
SketchCode code = getCode(codeIndex);
|
||||
if (dotJavaFilename.equals(code.getFileName())) {
|
||||
return new RunnerException(message, codeIndex, dotJavaLine);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run the build inside the temporary build folder.
|
||||
* @return null if compilation failed, main class name if not
|
||||
@ -1564,8 +1315,8 @@ public class Sketch {
|
||||
* @return null if compilation failed, main class name if not
|
||||
*/
|
||||
public String build(String buildPath, boolean verbose) throws RunnerException {
|
||||
String primaryClassName = name + ".cpp";
|
||||
Compiler compiler = new Compiler(this, buildPath, primaryClassName);
|
||||
String primaryClassName = data.getName() + ".cpp";
|
||||
Compiler compiler = new Compiler(data, buildPath, primaryClassName);
|
||||
File buildPrefsFile = new File(buildPath, BUILD_PREFS_FILE);
|
||||
String newBuildPrefs = buildPrefsString(compiler);
|
||||
|
||||
@ -1586,7 +1337,15 @@ public class Sketch {
|
||||
|
||||
// run the preprocessor
|
||||
editor.status.progressUpdate(20);
|
||||
preprocess(buildPath);
|
||||
|
||||
ensureExistence();
|
||||
|
||||
compiler.setProgressListener(new ProgressListener() {
|
||||
@Override
|
||||
public void progress(int percent) {
|
||||
editor.status.progressUpdate(percent);
|
||||
}
|
||||
});
|
||||
|
||||
// compile the program. errors will happen as a RunnerException
|
||||
// that will bubble up to whomever called build().
|
||||
@ -1632,11 +1391,6 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
public void setCompilingProgress(int percent) {
|
||||
editor.status.progressUpdate(percent);
|
||||
}
|
||||
|
||||
|
||||
protected void size(PreferencesMap prefs) throws RunnerException {
|
||||
String maxTextSizeString = prefs.get("upload.maximum_size");
|
||||
String maxDataSizeString = prefs.get("upload.maximum_data_size");
|
||||
@ -1773,8 +1527,8 @@ public class Sketch {
|
||||
folder.mkdirs();
|
||||
modified = true;
|
||||
|
||||
for (int i = 0; i < codeCount; i++) {
|
||||
codeDocs[i].getCode().save(); // this will force a save
|
||||
for (SketchCodeDocument codeDoc : data.getCodeDocs()) {
|
||||
codeDoc.getCode().save(); // this will force a save
|
||||
}
|
||||
calcModified();
|
||||
|
||||
@ -1808,9 +1562,9 @@ public class Sketch {
|
||||
// } else if (!folder.canWrite()) {
|
||||
|
||||
// check to see if each modified code file can be written to
|
||||
for (int i = 0; i < codeCount; i++) {
|
||||
if (codeDocs[i].getCode().isModified() && codeDocs[i].getCode().fileReadOnly() &&
|
||||
codeDocs[i].getCode().fileExists()) {
|
||||
for (SketchCodeDocument codeDoc : data.getCodeDocs()) {
|
||||
if (codeDoc.getCode().isModified() && codeDoc.getCode().fileReadOnly() &&
|
||||
codeDoc.getCode().fileExists()) {
|
||||
// System.err.println("found a read-only file " + code[i].file);
|
||||
return true;
|
||||
}
|
||||
@ -1879,7 +1633,7 @@ public class Sketch {
|
||||
* Returns the name of this sketch. (The pretty name of the main tab.)
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
|
||||
@ -1948,33 +1702,23 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
public String getClassPath() {
|
||||
return classPath;
|
||||
}
|
||||
|
||||
|
||||
public SketchCodeDocument[] getCodeDocs() {
|
||||
return codeDocs;
|
||||
return data.getCodeDocs();
|
||||
}
|
||||
|
||||
|
||||
public int getCodeCount() {
|
||||
return codeCount;
|
||||
return data.getCodeCount();
|
||||
}
|
||||
|
||||
|
||||
public SketchCode getCode(int index) {
|
||||
return codeDocs[index].getCode();
|
||||
return data.getCodeDoc(index).getCode();
|
||||
}
|
||||
|
||||
|
||||
public int getCodeIndex(SketchCode who) {
|
||||
for (int i = 0; i < codeCount; i++) {
|
||||
if (who == codeDocs[i].getCode()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return data.indexOfCode(who);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
SketchCode - data class for a single file inside a sketch
|
||||
Part of the Processing project - http://processing.org
|
||||
@ -31,11 +29,11 @@ import java.util.Arrays;
|
||||
import static processing.app.I18n._;
|
||||
import processing.app.helpers.FileUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a single tab of a sketch.
|
||||
*/
|
||||
public class SketchCode {
|
||||
|
||||
/** Pretty name (no extension), not the full file name */
|
||||
private String prettyName;
|
||||
|
||||
@ -47,8 +45,6 @@ public class SketchCode {
|
||||
|
||||
private boolean modified;
|
||||
|
||||
/** name of .java file after preproc */
|
||||
// private String preprocName;
|
||||
/** where this code starts relative to the concat'd code */
|
||||
private int preprocOffset;
|
||||
|
||||
|
108
app/src/processing/app/SketchData.java
Normal file
108
app/src/processing/app/SketchData.java
Normal file
@ -0,0 +1,108 @@
|
||||
package processing.app;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class SketchData {
|
||||
|
||||
/**
|
||||
* Name of sketch, which is the name of main file (without .pde or .java
|
||||
* extension)
|
||||
*/
|
||||
private String name;
|
||||
|
||||
private List<SketchCodeDocument> codeDocs = new ArrayList<SketchCodeDocument>();
|
||||
|
||||
private static final Comparator<SketchCodeDocument> CODE_DOCS_COMPARATOR = new Comparator<SketchCodeDocument>() {
|
||||
@Override
|
||||
public int compare(SketchCodeDocument cd1, SketchCodeDocument cd2) {
|
||||
return cd1.getCode().getFileName().compareTo(cd2.getCode().getFileName());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public int getCodeCount() {
|
||||
return codeDocs.size();
|
||||
}
|
||||
|
||||
public SketchCodeDocument[] getCodeDocs() {
|
||||
return codeDocs.toArray(new SketchCodeDocument[0]);
|
||||
}
|
||||
|
||||
public void addCodeDoc(SketchCodeDocument sketchCodeDoc) {
|
||||
codeDocs.add(sketchCodeDoc);
|
||||
}
|
||||
|
||||
public void moveCodeDocToFront(SketchCodeDocument codeDoc) {
|
||||
codeDocs.remove(codeDoc);
|
||||
codeDocs.add(0, codeDoc);
|
||||
}
|
||||
|
||||
protected void replaceCode(SketchCode newCode) {
|
||||
for (SketchCodeDocument codeDoc : codeDocs) {
|
||||
if (codeDoc.getCode().getFileName().equals(newCode.getFileName())) {
|
||||
codeDoc.setCode(newCode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void insertCode(SketchCode sketchCode) {
|
||||
addCodeDoc(new SketchCodeDocument(sketchCode, null));
|
||||
}
|
||||
|
||||
protected void sortCode() {
|
||||
if (codeDocs.size() < 2)
|
||||
return;
|
||||
SketchCodeDocument first = codeDocs.remove(0);
|
||||
Collections.sort(codeDocs, CODE_DOCS_COMPARATOR);
|
||||
codeDocs.add(0, first);
|
||||
}
|
||||
|
||||
public SketchCodeDocument getCodeDoc(int i) {
|
||||
return codeDocs.get(i);
|
||||
}
|
||||
|
||||
public SketchCode getCode(int i) {
|
||||
return codeDocs.get(i).getCode();
|
||||
}
|
||||
|
||||
protected void removeCode(SketchCode which) {
|
||||
for (SketchCodeDocument codeDoc : codeDocs) {
|
||||
if (codeDoc.getCode() == which) {
|
||||
codeDocs.remove(codeDoc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
System.err.println(_("removeCode: internal error.. could not find code"));
|
||||
}
|
||||
|
||||
public int indexOfCodeDoc(SketchCodeDocument codeDoc) {
|
||||
return codeDocs.indexOf(codeDoc);
|
||||
}
|
||||
|
||||
public int indexOfCode(SketchCode who) {
|
||||
for (SketchCodeDocument codeDoc : codeDocs) {
|
||||
if (codeDoc.getCode() == who) {
|
||||
return codeDocs.indexOf(codeDoc);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void clearCodeDocs() {
|
||||
codeDocs.clear();
|
||||
}
|
||||
}
|
@ -27,6 +27,8 @@ import static processing.app.I18n._;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -37,59 +39,84 @@ import java.util.Map;
|
||||
import processing.app.Base;
|
||||
import processing.app.I18n;
|
||||
import processing.app.Preferences;
|
||||
import processing.app.Sketch;
|
||||
import processing.app.SketchCode;
|
||||
import processing.app.SketchCodeDocument;
|
||||
import processing.app.SketchData;
|
||||
import processing.app.helpers.FileUtils;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
import processing.app.helpers.ProcessUtils;
|
||||
import processing.app.helpers.StringReplacer;
|
||||
import processing.app.helpers.filefilters.OnlyDirs;
|
||||
import processing.app.packages.Library;
|
||||
import processing.app.packages.LibraryList;
|
||||
import processing.app.preproc.PdePreprocessor;
|
||||
import processing.core.PApplet;
|
||||
|
||||
public class Compiler implements MessageConsumer {
|
||||
|
||||
private Sketch sketch;
|
||||
private SketchData sketch;
|
||||
private PreferencesMap prefs;
|
||||
private boolean verbose;
|
||||
|
||||
private List<File> objectFiles;
|
||||
|
||||
private PreferencesMap prefs;
|
||||
private boolean verbose;
|
||||
private boolean sketchIsCompiled;
|
||||
private String targetArch;
|
||||
|
||||
private RunnerException exception;
|
||||
|
||||
/**
|
||||
* Listener interface for progress update on the GUI
|
||||
*/
|
||||
public interface ProgressListener {
|
||||
public void progress(int percent);
|
||||
}
|
||||
|
||||
private ProgressListener progressListener;
|
||||
|
||||
/**
|
||||
* Create a new Compiler
|
||||
* @param _sketch Sketch object to be compiled.
|
||||
* @param _buildPath Where the temporary files live and will be built from.
|
||||
* @param _primaryClassName the name of the combined sketch file w/ extension
|
||||
*/
|
||||
public Compiler(Sketch _sketch, String _buildPath, String _primaryClassName)
|
||||
public Compiler(SketchData _sketch, String _buildPath, String _primaryClassName)
|
||||
throws RunnerException {
|
||||
sketch = _sketch;
|
||||
prefs = createBuildPreferences(_buildPath, _primaryClassName);
|
||||
|
||||
// Start with an empty progress listener
|
||||
progressListener = new ProgressListener() {
|
||||
@Override
|
||||
public void progress(int percent) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void setProgressListener(ProgressListener _progressListener) {
|
||||
progressListener = _progressListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile sketch.
|
||||
* @param buildPath
|
||||
*
|
||||
* @return true if successful.
|
||||
* @throws RunnerException Only if there's a problem. Only then.
|
||||
*/
|
||||
public boolean compile(boolean _verbose) throws RunnerException {
|
||||
preprocess(prefs.get("build.path"));
|
||||
|
||||
verbose = _verbose || Preferences.getBoolean("build.verbose");
|
||||
sketchIsCompiled = false;
|
||||
objectFiles = new ArrayList<File>();
|
||||
|
||||
// 0. include paths for core + all libraries
|
||||
sketch.setCompilingProgress(20);
|
||||
progressListener.progress(20);
|
||||
List<File> includeFolders = new ArrayList<File>();
|
||||
includeFolders.add(prefs.getFile("build.core.path"));
|
||||
if (prefs.getFile("build.variant.path") != null)
|
||||
includeFolders.add(prefs.getFile("build.variant.path"));
|
||||
for (Library lib : sketch.getImportedLibraries()) {
|
||||
for (Library lib : importedLibraries) {
|
||||
if (verbose)
|
||||
System.out.println(I18n
|
||||
.format(_("Using library {0} in folder: {1} {2}"), lib.getName(),
|
||||
@ -105,7 +132,7 @@ public class Compiler implements MessageConsumer {
|
||||
String[] overrides = prefs.get("architecture.override_check").split(",");
|
||||
archs.addAll(Arrays.asList(overrides));
|
||||
}
|
||||
for (Library lib : sketch.getImportedLibraries()) {
|
||||
for (Library lib : importedLibraries) {
|
||||
if (!lib.supportsArchitecture(archs)) {
|
||||
System.err.println(I18n
|
||||
.format(_("WARNING: library {0} claims to run on {1} "
|
||||
@ -117,33 +144,33 @@ public class Compiler implements MessageConsumer {
|
||||
}
|
||||
|
||||
// 1. compile the sketch (already in the buildPath)
|
||||
sketch.setCompilingProgress(30);
|
||||
progressListener.progress(30);
|
||||
compileSketch(includeFolders);
|
||||
sketchIsCompiled = true;
|
||||
|
||||
// 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
|
||||
// Doesn't really use configPreferences
|
||||
sketch.setCompilingProgress(40);
|
||||
progressListener.progress(40);
|
||||
compileLibraries(includeFolders);
|
||||
|
||||
// 3. compile the core, outputting .o files to <buildPath> and then
|
||||
// collecting them into the core.a library file.
|
||||
sketch.setCompilingProgress(50);
|
||||
progressListener.progress(50);
|
||||
compileCore();
|
||||
|
||||
// 4. link it all together into the .elf file
|
||||
sketch.setCompilingProgress(60);
|
||||
progressListener.progress(60);
|
||||
compileLink();
|
||||
|
||||
// 5. extract EEPROM data (from EEMEM directive) to .eep file.
|
||||
sketch.setCompilingProgress(70);
|
||||
progressListener.progress(70);
|
||||
compileEep();
|
||||
|
||||
// 6. build the .hex file
|
||||
sketch.setCompilingProgress(80);
|
||||
progressListener.progress(80);
|
||||
compileHex();
|
||||
|
||||
sketch.setCompilingProgress(90);
|
||||
progressListener.progress(90);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -190,8 +217,7 @@ public class Compiler implements MessageConsumer {
|
||||
|
||||
p.put("build.path", _buildPath);
|
||||
p.put("build.project_name", _primaryClassName);
|
||||
targetArch = targetPlatform.getId();
|
||||
p.put("build.arch", targetArch.toUpperCase());
|
||||
p.put("build.arch", targetPlatform.getId().toUpperCase());
|
||||
|
||||
// Platform.txt should define its own compiler.path. For
|
||||
// compatibility with earlier 1.5 versions, we define a (ugly,
|
||||
@ -356,8 +382,6 @@ public class Compiler implements MessageConsumer {
|
||||
return ret;
|
||||
}
|
||||
|
||||
boolean firstErrorFound;
|
||||
boolean secondErrorFound;
|
||||
|
||||
/**
|
||||
* Either succeeds or throws a RunnerException fit for public consumption.
|
||||
@ -382,9 +406,6 @@ public class Compiler implements MessageConsumer {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
firstErrorFound = false; // haven't found any errors yet
|
||||
secondErrorFound = false;
|
||||
|
||||
Process process;
|
||||
try {
|
||||
process = ProcessUtils.exec(command);
|
||||
@ -520,7 +541,7 @@ public class Compiler implements MessageConsumer {
|
||||
if (!sketchIsCompiled) {
|
||||
// Place errors when compiling the sketch, but never while compiling libraries
|
||||
// or the core. The user's sketch might contain the same filename!
|
||||
e = sketch.placeException(error, pieces[1], PApplet.parseInt(pieces[2]) - 1);
|
||||
e = placeException(error, pieces[1], PApplet.parseInt(pieces[2]) - 1);
|
||||
}
|
||||
|
||||
// replace full file path with the name of the sketch tab (unless we're
|
||||
@ -656,7 +677,7 @@ public class Compiler implements MessageConsumer {
|
||||
// 2. compile the libraries, outputting .o files to:
|
||||
// <buildPath>/<library>/
|
||||
void compileLibraries(List<File> includeFolders) throws RunnerException {
|
||||
for (Library lib : sketch.getImportedLibraries()) {
|
||||
for (Library lib : importedLibraries) {
|
||||
compileLibrary(lib, includeFolders);
|
||||
}
|
||||
}
|
||||
@ -853,4 +874,144 @@ public class Compiler implements MessageConsumer {
|
||||
public PreferencesMap getBuildPreferences() {
|
||||
return prefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build all the code for this sketch.
|
||||
*
|
||||
* In an advanced program, the returned class name could be different,
|
||||
* which is why the className is set based on the return value.
|
||||
* A compilation error will burp up a RunnerException.
|
||||
*
|
||||
* Setting purty to 'true' will cause exception line numbers to be incorrect.
|
||||
* Unless you know the code compiles, you should first run the preprocessor
|
||||
* with purty set to false to make sure there are no errors, then once
|
||||
* successful, re-export with purty set to true.
|
||||
*
|
||||
* @param buildPath Location to copy all the .java files
|
||||
* @return null if compilation failed, main class name if not
|
||||
*/
|
||||
public void preprocess(String buildPath) throws RunnerException {
|
||||
preprocess(buildPath, new PdePreprocessor());
|
||||
}
|
||||
|
||||
public void preprocess(String buildPath, PdePreprocessor preprocessor) throws RunnerException {
|
||||
|
||||
// 1. concatenate all .pde files to the 'main' pde
|
||||
// store line number for starting point of each code bit
|
||||
|
||||
StringBuffer bigCode = new StringBuffer();
|
||||
int bigCount = 0;
|
||||
for (SketchCodeDocument scd : sketch.getCodeDocs()) {
|
||||
SketchCode sc = scd.getCode();
|
||||
if (sc.isExtension("ino") || sc.isExtension("pde")) {
|
||||
sc.setPreprocOffset(bigCount);
|
||||
// These #line directives help the compiler report errors with
|
||||
// correct the filename and line number (issue 281 & 907)
|
||||
bigCode.append("#line 1 \"" + sc.getFileName() + "\"\n");
|
||||
bigCode.append(sc.getProgram());
|
||||
bigCode.append('\n');
|
||||
bigCount += sc.getLineCount();
|
||||
}
|
||||
}
|
||||
|
||||
// Note that the headerOffset isn't applied until compile and run, because
|
||||
// it only applies to the code after it's been written to the .java file.
|
||||
int headerOffset = 0;
|
||||
try {
|
||||
headerOffset = preprocessor.writePrefix(bigCode.toString());
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
fnfe.printStackTrace();
|
||||
String msg = _("Build folder disappeared or could not be written");
|
||||
throw new RunnerException(msg);
|
||||
}
|
||||
|
||||
// 2. run preproc on that code using the sugg class name
|
||||
// to create a single .java file and write to buildpath
|
||||
|
||||
try {
|
||||
// Output file
|
||||
File streamFile = new File(buildPath, sketch.getName() + ".cpp");
|
||||
FileOutputStream outputStream = new FileOutputStream(streamFile);
|
||||
preprocessor.write(outputStream);
|
||||
outputStream.close();
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
fnfe.printStackTrace();
|
||||
String msg = _("Build folder disappeared or could not be written");
|
||||
throw new RunnerException(msg);
|
||||
} catch (RunnerException pe) {
|
||||
// RunnerExceptions are caught here and re-thrown, so that they don't
|
||||
// get lost in the more general "Exception" handler below.
|
||||
throw pe;
|
||||
|
||||
} catch (Exception ex) {
|
||||
// TODO better method for handling this?
|
||||
System.err.println(I18n.format(_("Uncaught exception type: {0}"), ex.getClass()));
|
||||
ex.printStackTrace();
|
||||
throw new RunnerException(ex.toString());
|
||||
}
|
||||
|
||||
// grab the imports from the code just preproc'd
|
||||
|
||||
importedLibraries = new LibraryList();
|
||||
for (String item : preprocessor.getExtraImports()) {
|
||||
Library lib = Base.importToLibraryTable.get(item);
|
||||
if (lib != null && !importedLibraries.contains(lib)) {
|
||||
importedLibraries.add(lib);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. then loop over the code[] and save each .java file
|
||||
|
||||
for (SketchCodeDocument scd : sketch.getCodeDocs()) {
|
||||
SketchCode sc = scd.getCode();
|
||||
if (sc.isExtension("c") || sc.isExtension("cpp") || sc.isExtension("h")) {
|
||||
// no pre-processing services necessary for java files
|
||||
// just write the the contents of 'program' to a .java file
|
||||
// into the build directory. uses byte stream and reader/writer
|
||||
// shtuff so that unicode bunk is properly handled
|
||||
String filename = sc.getFileName(); //code[i].name + ".java";
|
||||
try {
|
||||
Base.saveFile(sc.getProgram(), new File(buildPath, filename));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RunnerException(I18n.format(_("Problem moving {0} to the build folder"), filename));
|
||||
}
|
||||
|
||||
} else if (sc.isExtension("ino") || sc.isExtension("pde")) {
|
||||
// The compiler and runner will need this to have a proper offset
|
||||
sc.addPreprocOffset(headerOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List of library folders.
|
||||
*/
|
||||
private LibraryList importedLibraries;
|
||||
|
||||
/**
|
||||
* Map an error from a set of processed .java files back to its location
|
||||
* in the actual sketch.
|
||||
* @param message The error message.
|
||||
* @param dotJavaFilename The .java file where the exception was found.
|
||||
* @param dotJavaLine Line number of the .java file for the exception (0-indexed!)
|
||||
* @return A RunnerException to be sent to the editor, or null if it wasn't
|
||||
* possible to place the exception to the sketch code.
|
||||
*/
|
||||
public RunnerException placeException(String message,
|
||||
String dotJavaFilename,
|
||||
int dotJavaLine) {
|
||||
// Placing errors is simple, because we inserted #line directives
|
||||
// into the preprocessed source. The compiler gives us correct
|
||||
// the file name and line number. :-)
|
||||
for (SketchCodeDocument codeDoc : sketch.getCodeDocs()) {
|
||||
SketchCode code = codeDoc.getCode();
|
||||
if (dotJavaFilename.equals(code.getFileName())) {
|
||||
return new RunnerException(message, sketch.indexOfCode(code), dotJavaLine);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user