void applyDirectives() { findRemoveDirectives(true); StringBuffer buffer = new StringBuffer(); String head = "", toe = "; \n"; if (crispBox.isSelected()) buffer.append(head + "crisp=true" + toe); if (!fontField.getText().trim().equals("")) buffer.append(head + "font=\"" + fontField.getText().trim() + "\"" + toe); if (globalKeyEventsBox.isSelected()) buffer.append(head + "globalKeyEvents=true" + toe); if (pauseOnBlurBox.isSelected()) buffer.append(head + "pauseOnBlur=true" + toe); if (!preloadField.getText().trim().equals("")) buffer.append(head + "preload=\"" + preloadField.getText().trim() + "\"" + toe); /*if ( transparentBox.isSelected() ) buffer.append( head + "transparent=true" + toe );*/ Sketch sketch = editor.getSketch(); SketchCode code = sketch.getCode(0); // first tab if (buffer.length() > 0) { code.setProgram("/* @pjs " + buffer.toString() + " */\n\n" + code.getProgram()); if (sketch.getCurrentCode() == code) // update textarea if on first tab { editor.setText(sketch.getCurrentCode().getProgram()); editor.setSelection(0, 0); } sketch.setModified(false); sketch.setModified(true); } }
// TODO Why is this necessary? Why isn't Sketch.isModified() used? private static boolean isSketchModified(Sketch sketch) { for (SketchCode sc : sketch.getCode()) { if (sc.isModified()) { return true; } } return false; }
void findRemoveDirectives(boolean clean) { // if ( clean ) editor.startCompoundEdit(); Sketch sketch = editor.getSketch(); for (int i = 0; i < sketch.getCodeCount(); i++) { SketchCode code = sketch.getCode(i); String program = code.getProgram(); StringBuffer buffer = new StringBuffer(); Matcher m = pjsPattern.matcher(program); while (m.find()) { String mm = m.group(); // TODO this urgently needs tests .. /* remove framing */ mm = mm.replaceAll("^\\/\\*\\s*@pjs", "").replaceAll("\\s*\\*\\/\\s*$", ""); /* fix multiline nice formatting */ mm = mm.replaceAll("[\\s]*([^;\\s\\n\\r]+)[\\s]*,[\\s]*[\\n\\r]+", "$1,"); /* fix multiline version without semicolons */ mm = mm.replaceAll("[\\s]*([^;\\s\\n\\r]+)[\\s]*[\\n\\r]+", "$1;"); mm = mm.replaceAll("\n", " ").replaceAll("\r", " "); // System.out.println(mm); if (clean) { m.appendReplacement(buffer, ""); } else { String[] directives = mm.split(";"); for (String d : directives) { // System.out.println(d); parseDirective(d); } } } if (clean) { m.appendTail(buffer); // TODO: not working! code.setProgram(buffer.toString()); code.setModified(true); } } if (clean) { // editor.stopCompoundEdit(); editor.setText(sketch.getCurrentCode().getProgram()); sketch.setModified(false); sketch.setModified(true); } }
/** * Part of the MessageConsumer interface, this is called * whenever a piece (usually a line) of error message is spewed * out from the compiler. The errors are parsed for their contents * and line number, which is then reported back to Editor. */ public void message(String s) { int i; System.out.println("**************[ROBOTIS]***********************************"); // remove the build path so people only see the filename // can't use replaceAll() because the path may have characters in it which // have meaning in a regular expression. if (!verbose) { while ((i = s.indexOf(buildPath + File.separator)) != -1) { s = s.substring(0, i) + s.substring(i + (buildPath + File.separator).length()); } } // look for error line, which contains file name, line number, // and at least the first line of the error message String errorFormat = "([\\w\\d_]+.\\w+):(\\d+):\\s*error:\\s*(.*)\\s*"; String[] pieces = PApplet.match(s, errorFormat); // if (pieces != null && exception == null) { // exception = sketch.placeException(pieces[3], pieces[1], PApplet.parseInt(pieces[2]) - 1); // if (exception != null) exception.hideStackTrace(); // } if (pieces != null) { String error = pieces[3], msg = ""; if (pieces[3].trim().equals("SPI.h: No such file or directory")) { error = _("Please import the SPI library from the Sketch > Import Library menu."); msg = _("\nAs of Arduino 0019, the Ethernet library depends on the SPI library." + "\nYou appear to be using it or another library that depends on the SPI library.\n\n"); } if (pieces[3].trim().equals("'BYTE' was not declared in this scope")) { error = _("The 'BYTE' keyword is no longer supported."); msg = _("\nAs of Arduino 1.0, the 'BYTE' keyword is no longer supported." + "\nPlease use Serial.write() instead.\n\n"); } if (pieces[3].trim().equals("no matching function for call to 'Server::Server(int)'")) { error = _("The Server class has been renamed EthernetServer."); msg = _("\nAs of Arduino 1.0, the Server class in the Ethernet library " + "has been renamed to EthernetServer.\n\n"); } if (pieces[3].trim().equals("no matching function for call to 'Client::Client(byte [4], int)'")) { error = _("The Client class has been renamed EthernetClient."); msg = _("\nAs of Arduino 1.0, the Client class in the Ethernet library " + "has been renamed to EthernetClient.\n\n"); } if (pieces[3].trim().equals("'Udp' was not declared in this scope")) { error = _("The Udp class has been renamed EthernetUdp."); msg = _("\nAs of Arduino 1.0, the Udp class in the Ethernet library " + "has been renamed to EthernetUdp.\n\n"); } if (pieces[3].trim().equals("'class TwoWire' has no member named 'send'")) { error = _("Wire.send() has been renamed Wire.write()."); msg = _("\nAs of Arduino 1.0, the Wire.send() function was renamed " + "to Wire.write() for consistency with other libraries.\n\n"); } if (pieces[3].trim().equals("'class TwoWire' has no member named 'receive'")) { error = _("Wire.receive() has been renamed Wire.read()."); msg = _("\nAs of Arduino 1.0, the Wire.receive() function was renamed " + "to Wire.read() for consistency with other libraries.\n\n"); } if (pieces[3].trim().equals("'Mouse' was not declared in this scope")) { error = _("'Mouse' only supported on the Arduino Leonardo"); //msg = _("\nThe 'Mouse' class is only supported on the Arduino Leonardo.\n\n"); } if (pieces[3].trim().equals("'Keyboard' was not declared in this scope")) { error = _("'Keyboard' only supported on the Arduino Leonardo"); //msg = _("\nThe 'Keyboard' class is only supported on the Arduino Leonardo.\n\n"); } RunnerException e = null; 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); } // replace full file path with the name of the sketch tab (unless we're // in verbose mode, in which case don't modify the compiler output) if (e != null && !verbose) { SketchCode code = sketch.getCode(e.getCodeIndex()); String fileName = (code.isExtension("ino") || code.isExtension("pde")) ? code.getPrettyName() : code.getFileName(); int lineNum = e.getCodeLine() + 1; s = fileName + ":" + lineNum + ": error: " + pieces[3] + msg; } if (exception == null && e != null) { exception = e; exception.hideStackTrace(); } } System.err.print(s); }
private String getTitle(PicodeEditor picodeEditor) { SketchCode code = picodeEditor.getCode(); return code.isExtension("pde") ? code.getPrettyName() : code.getFileName(); }
/** * Fetches code from the editor tabs and pre-processes it into parsable pure java source. And * there's a difference between parsable and compilable. XQPrerocessor.java makes this code * compilable. <br> * Handles: * <li>Removal of import statements * <li>Conversion of int(), char(), etc to (int)(), (char)(), etc. * <li>Replacing '#' with 0xff for color representation * <li>Converts all 'color' datatypes to int (experimental) * <li>Appends class declaration statement after determining the mode the sketch is in - ACTIVE or * STATIC * * @return String - Pure java representation of PDE code. Note that this code is not yet compile * ready. */ private String preprocessCode() { String sourceAlt = ""; programImports = new ArrayList<ImportStatement>(); if (editor == null) { try { sourceAlt = readFile(PATH); } catch (IOException e) { e.printStackTrace(); } System.out.println(sourceAlt); System.out.println("-----------PreProcessed----------"); return sourceAlt; } // Super wicked regular expressions! (Used from Processing source) final Pattern FUNCTION_DECL = Pattern.compile( "(^|;)\\s*((public|private|protected|final|static)\\s+)*" + "(void|int|float|double|String|char|byte)" + "(\\s*\\[\\s*\\])?\\s+[a-zA-Z0-9]+\\s*\\(", Pattern.MULTILINE); // Handle code input from editor/java file try { if (editor == null) { System.out.println("Reading .java file: " + PATH); } else { rawCode = new StringBuffer(); for (SketchCode sc : editor.getSketch().getCode()) { if (sc.isExtension("pde")) { sc.setPreprocOffset(scPreProcOffset); try { if (editor.getSketch().getCurrentCode().equals(sc)) { // rawCode.append(sc.getDocument().getText(0, // sc.getDocument().getLength())); rawCode.append( scrapImportStatements( sc.getDocument().getText(0, sc.getDocument().getLength()), editor.getSketch().getCodeIndex(sc))); } else { // rawCode.append(sc.getProgram()); rawCode.append( scrapImportStatements(sc.getProgram(), editor.getSketch().getCodeIndex(sc))); } rawCode.append('\n'); } catch (Exception e) { System.err.println("Exception in preprocessCode() - bigCode " + e.toString()); } rawCode.append('\n'); scPreProcOffset += sc.getLineCount(); } } sourceAlt = rawCode.toString(); // System.out.println("Obtaining source from editor."); } } catch (Exception e) { System.out.println("Exception in preprocessCode()"); } // Replace comments with whitespaces // sourceAlt = scrubComments(sourceAlt); // Find all int(*), replace with PApplet.parseInt(*) // \bint\s*\(\s*\b , i.e all exclusive "int(" String dataTypeFunc[] = {"int", "char", "float", "boolean", "byte"}; for (String dataType : dataTypeFunc) { String dataTypeRegexp = "\\b" + dataType + "\\s*\\("; Pattern pattern = Pattern.compile(dataTypeRegexp); Matcher matcher = pattern.matcher(sourceAlt); // while (matcher.find()) { // System.out.print("Start index: " + matcher.start()); // System.out.println(" End index: " + matcher.end() + " "); // System.out.println("-->" + matcher.group() + "<--"); // } sourceAlt = matcher.replaceAll( "PApplet.parse" + Character.toUpperCase(dataType.charAt(0)) + dataType.substring(1) + "("); } // Find all #[web color] and replace with 0xff[webcolor] // Should be 6 digits only. final String webColorRegexp = "#{1}[A-F|a-f|0-9]{6}\\W"; Pattern webPattern = Pattern.compile(webColorRegexp); Matcher webMatcher = webPattern.matcher(sourceAlt); while (webMatcher.find()) { // System.out.println("Found at: " + webMatcher.start()); String found = sourceAlt.substring(webMatcher.start(), webMatcher.end()); // System.out.println("-> " + found); sourceAlt = webMatcher.replaceFirst("0xff" + found.substring(1)); webMatcher = webPattern.matcher(sourceAlt); } // TODO: Experimental. // Replace all color data types with int // Regex, Y U SO powerful? final String colorTypeRegex = "color(?![a-zA-Z0-9_])(?=\\[*)(?!(\\s*\\())"; Pattern colorPattern = Pattern.compile(colorTypeRegex); Matcher colorMatcher = colorPattern.matcher(sourceAlt); sourceAlt = colorMatcher.replaceAll("int"); checkForChangedImports(); className = (editor == null) ? "DefaultClass" : editor.getSketch().getName(); // Check whether the code is being written in STATIC mode(no function // declarations) - append class declaration and void setup() declaration Matcher matcher = FUNCTION_DECL.matcher(sourceAlt); if (!matcher.find()) { sourceAlt = "public class " + className + " extends PApplet {\n" + "public void setup() {\n" + sourceAlt + "\nnoLoop();\n}\n" + "\n}\n"; staticMode = true; mainClassOffset = 2; } else { sourceAlt = "public class " + className + " extends PApplet {\n" + sourceAlt + "\n}"; staticMode = false; mainClassOffset = 1; } // Handle unicode characters sourceAlt = substituteUnicode(sourceAlt); // System.out.println("-->\n" + sourceAlt + "\n<--"); // System.out.println("PDE code processed - " // + editor.getSketch().getName()); sourceCode = sourceAlt; return sourceAlt; }
/** * Calculates the tab number and line number of the error in that particular tab. Provides mapping * between pure java and pde code. * * @param problem - IProblem * @return int[0] - tab number, int[1] - line number */ public int[] calculateTabIndexAndLineNumber(IProblem problem) { // String[] lines = {};// = PApplet.split(sourceString, '\n'); int codeIndex = 0; int bigCount = 0; int x = problem.getSourceLineNumber() - mainClassOffset; if (x < 0) { // System.out.println("Negative line number " // + problem.getSourceLineNumber() + " , offset " // + mainClassOffset); x = problem.getSourceLineNumber() - 2; // Another -1 for 0 index if (x < programImports.size() && x >= 0) { ImportStatement is = programImports.get(x); // System.out.println(is.importName + ", " + is.tab + ", " // + is.lineNumber); return new int[] {is.tab, is.lineNumber}; } else { // Some seriously ugly stray error, just can't find the source // line! Simply return first line for first tab. return new int[] {0, 1}; } } try { for (SketchCode sc : editor.getSketch().getCode()) { if (sc.isExtension("pde")) { sc.setPreprocOffset(bigCount); int len = 0; if (editor.getSketch().getCurrentCode().equals(sc)) { len = Base.countLines(sc.getDocument().getText(0, sc.getDocument().getLength())) + 1; } else { len = Base.countLines(sc.getProgram()) + 1; } // System.out.println("x,len, CI: " + x + "," + len + "," // + codeIndex); if (x >= len) { // We're in the last tab and the line count is greater // than the no. // of lines in the tab, if (codeIndex >= editor.getSketch().getCodeCount() - 1) { // System.out.println("Exceeds lc " + x + "," + len // + problem.toString()); // x = len x = editor.getSketch().getCode(codeIndex).getLineCount(); // TODO: Obtain line having last non-white space // character in the code. break; } else { x -= len; codeIndex++; } } else { if (codeIndex >= editor.getSketch().getCodeCount()) codeIndex = editor.getSketch().getCodeCount() - 1; break; } } bigCount += sc.getLineCount(); } } catch (Exception e) { System.err.println( "Things got messed up in ErrorCheckerService.calculateTabIndexAndLineNumber()"); } return new int[] {codeIndex, x}; }