1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

A good start on the error parsers/hyperlinks for Arduino.

Change-Id: I5f3a3565970d177392ca6af569a3447aabe1be81
This commit is contained in:
Doug Schaefer 2015-08-16 23:04:38 -04:00
parent f635f6c7d8
commit 81f6bd0259
11 changed files with 311 additions and 33 deletions

View file

@ -26,6 +26,8 @@ import org.eclipse.cdt.arduino.core.internal.board.ArduinoPackage;
import org.eclipse.cdt.arduino.core.internal.board.ArduinoPlatform;
import org.eclipse.cdt.arduino.core.internal.board.ArduinoTool;
import org.eclipse.cdt.arduino.core.internal.board.ToolDependency;
import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleParser;
import org.eclipse.cdt.arduino.core.internal.console.ArduinoErrorParser;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
@ -37,6 +39,7 @@ import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
@ -493,4 +496,40 @@ public class ArduinoBuildConfiguration {
}
}
public ArduinoConsoleParser[] getBuildConsoleParsers() {
// ../src/Test.cpp:4:1: error: 'x' was not declared in this scope
return new ArduinoConsoleParser[] { new ArduinoErrorParser("(.*?):(\\d+):(\\d+:)? error: (.*)") { //$NON-NLS-1$
@Override
protected int getSeverity(Matcher matcher) {
return IMarker.SEVERITY_ERROR;
}
@Override
protected String getMessage(Matcher matcher) {
return matcher.group(4);
}
@Override
protected int getLineNumber(Matcher matcher) {
return Integer.parseInt(matcher.group(2));
}
@Override
protected String getFileName(Matcher matcher) {
return matcher.group(1);
}
@Override
protected int getLinkOffset(Matcher matcher) {
return 0;
}
@Override
protected int getLinkLength(Matcher matcher) {
return matcher.group(1).length() + 1 + matcher.group(2).length() + 1 + matcher.group(3).length();
}
} };
}
}

View file

@ -16,6 +16,7 @@ import java.util.regex.Pattern;
import org.eclipse.cdt.arduino.core.internal.Activator;
import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleService;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IncrementalProjectBuilder;
@ -36,6 +37,8 @@ public class ArduinoBuilder extends IncrementalProjectBuilder {
protected IProject[] build(int kind, Map<String, String> args, IProgressMonitor monitor) throws CoreException {
IProject project = getProject();
try {
project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
ArduinoConsoleService consoleService = Activator.getConsoleService();
consoleService.writeOutput(String.format("\nBuilding %s\n", project.getName()));
@ -47,7 +50,7 @@ public class ArduinoBuilder extends IncrementalProjectBuilder {
config.setEnvironment(processBuilder.environment());
Process process = processBuilder.start();
consoleService.monitor(process, null);
consoleService.monitor(process, config.getBuildConsoleParsers(), config.getBuildFolder());
if (process.exitValue() == 0) {
showSizes(config, consoleService);
@ -66,6 +69,8 @@ public class ArduinoBuilder extends IncrementalProjectBuilder {
protected void clean(IProgressMonitor monitor) throws CoreException {
try {
IProject project = getProject();
project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
ArduinoConsoleService consoleService = Activator.getConsoleService();
consoleService.writeOutput(String.format("\nCleaning %s\n", project.getName()));
@ -76,7 +81,7 @@ public class ArduinoBuilder extends IncrementalProjectBuilder {
config.setEnvironment(processBuilder.environment());
Process process = processBuilder.start();
consoleService.monitor(process, null);
consoleService.monitor(process, config.getBuildConsoleParsers(), config.getBuildFolder());
config.getBuildFolder().refreshLocal(IResource.DEPTH_INFINITE, monitor);
} catch (IOException e) {

View file

@ -1,8 +1,16 @@
package org.eclipse.cdt.arduino.core.internal.console;
import java.nio.file.Path;
public abstract class ArduinoConsoleParser {
public interface ConsoleParser {
private final String pattern;
private final int flags;
private final String lineQualifier;
protected ArduinoConsoleParser(String pattern, int flags, String lineQualifier) {
this.pattern = pattern;
this.flags = flags;
this.lineQualifier = lineQualifier;
}
/**
* Returns the pattern to be used for matching. The pattern is a string
@ -10,7 +18,9 @@ public interface ConsoleParser {
*
* @return the regular expression to be used for matching
*/
public String getPattern();
public String getPattern() {
return pattern;
}
/**
* Returns the flags to use when compiling this pattern match listener's
@ -21,7 +31,9 @@ public interface ConsoleParser {
* regular expression
* @see java.util.regex.Pattern#compile(java.lang.String, int)
*/
public int getCompilerFlags();
public int getCompilerFlags() {
return flags;
}
/**
* Returns a simple regular expression used to identify lines that may match
@ -34,15 +46,8 @@ public interface ConsoleParser {
* @return a simple regular expression used to identify lines that may match
* this pattern matcher's complete pattern, or <code>null</code>
*/
public String getLineQualifier();
/**
* The pattern has been matched. Perform any necessary actions. Generally
* this would include creating markers for the errors.
*
* @param text text that matched the pattern
* @param directory calculated current directory
*/
public void patternMatched(String text, Path directory);
public String getLineQualifier() {
return lineQualifier;
}
}

View file

@ -12,14 +12,11 @@ package org.eclipse.cdt.arduino.core.internal.console;
import java.io.IOException;
import org.eclipse.core.resources.IFolder;
public interface ArduinoConsoleService {
/**
* Capture the output for the process and display on the console.
*
* @param process
*/
void monitor(Process process, ConsoleParser[] consoleParsers) throws IOException;
void monitor(Process process, ArduinoConsoleParser[] consoleParsers, IFolder buildDirectory) throws IOException;
void writeOutput(String msg) throws IOException;

View file

@ -0,0 +1,67 @@
package org.eclipse.cdt.arduino.core.internal.console;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.arduino.core.internal.Activator;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
public abstract class ArduinoErrorParser extends ArduinoConsoleParser {
public static final String LINK_OFFSET = "arduino.link.offset"; //$NON-NLS-1$
public static final String LINK_LENGTH = "arduino.link.length"; //$NON-NLS-1$
private final Pattern errorPattern;
public ArduinoErrorParser(String pattern, int flags, String lineQualifier) {
super(pattern, flags, lineQualifier);
this.errorPattern = Pattern.compile(pattern);
}
public ArduinoErrorParser(String pattern) {
this(pattern, 0, null);
}
protected abstract String getFileName(Matcher matcher);
protected abstract int getLineNumber(Matcher matcher);
protected abstract String getMessage(Matcher matcher);
protected abstract int getSeverity(Matcher matcher);
protected abstract int getLinkOffset(Matcher matcher);
protected abstract int getLinkLength(Matcher matcher);
public IMarker generateMarker(IFolder buildDirectory, String text) {
Matcher matcher = errorPattern.matcher(text);
if (matcher.matches()) {
String fileName = getFileName(matcher);
IFile file = buildDirectory.getFile(fileName);
if (file.exists()) {
try {
IMarker marker = file.createMarker(ICModelMarker.C_MODEL_PROBLEM_MARKER);
marker.setAttribute(IMarker.MESSAGE, getMessage(matcher));
marker.setAttribute(IMarker.SEVERITY, getSeverity(matcher));
marker.setAttribute(IMarker.LINE_NUMBER, getLineNumber(matcher));
marker.setAttribute(IMarker.CHAR_START, -1);
marker.setAttribute(IMarker.CHAR_END, -1);
marker.setAttribute(LINK_OFFSET, getLinkOffset(matcher));
marker.setAttribute(LINK_LENGTH, getLinkLength(matcher));
return marker;
} catch (CoreException e) {
Activator.log(e);
return null;
}
}
}
return null;
}
}

View file

@ -48,13 +48,16 @@ public class ArduinoLaunchConfigurationDelegate extends LaunchConfigurationDeleg
public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor)
throws CoreException {
IRemoteConnection target = getTarget(configuration);
ArduinoRemoteConnection arduinoTarget = target.getService(ArduinoRemoteConnection.class);
ArduinoBoard targetBoard = arduinoTarget.getBoard();
if (target != null) {
ArduinoRemoteConnection arduinoTarget = target.getService(ArduinoRemoteConnection.class);
ArduinoBoard targetBoard = arduinoTarget.getBoard();
// 1. make sure proper build config is set active
IProject project = configuration.getMappedResources()[0].getProject();
ArduinoBuildConfiguration arduinoConfig = ArduinoBuildConfiguration.getConfig(project, targetBoard, monitor);
arduinoConfig.setActive(monitor);
// 1. make sure proper build config is set active
IProject project = configuration.getMappedResources()[0].getProject();
ArduinoBuildConfiguration arduinoConfig = ArduinoBuildConfiguration.getConfig(project, targetBoard,
monitor);
arduinoConfig.setActive(monitor);
}
// 2. Run the build
return super.buildForLaunch(configuration, mode, monitor);
@ -102,7 +105,7 @@ public class ArduinoLaunchConfigurationDelegate extends LaunchConfigurationDeleg
arduinoConfig.setEnvironment(processBuilder.environment());
Process process = processBuilder.start();
consoleService.monitor(process, null);
consoleService.monitor(process, null, null);
try {
process.waitFor();
} catch (InterruptedException e) {

View file

@ -8,6 +8,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.expressions,
org.eclipse.ui,
org.eclipse.ui.forms,
org.eclipse.jface.text;bundle-version="3.10.0",
org.eclipse.ui.console,
org.eclipse.ui.ide,
org.eclipse.debug.ui,

View file

@ -13,12 +13,20 @@ package org.eclipse.cdt.arduino.ui.internal.launch;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleParser;
import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleService;
import org.eclipse.cdt.arduino.core.internal.console.ConsoleParser;
import org.eclipse.cdt.arduino.core.internal.console.ArduinoErrorParser;
import org.eclipse.cdt.arduino.ui.internal.Activator;
import org.eclipse.cdt.arduino.ui.internal.Messages;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.console.ConsolePlugin;
@ -26,12 +34,15 @@ import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;
public class ArduinoConsole implements ArduinoConsoleService {
public class ArduinoConsole implements ArduinoConsoleService, IResourceChangeListener {
private static MessageConsole console;
private static MessageConsoleStream out;
private static MessageConsoleStream err;
private IFolder buildDirectory;
List<ArduinoPatternMatchListener> listeners = new ArrayList<>();
public ArduinoConsole() {
if (console == null) {
console = new MessageConsole(Messages.ArduinoLaunchConsole_0, null);
@ -48,12 +59,52 @@ public class ArduinoConsole implements ArduinoConsoleService {
err.setColor(display.getSystemColor(SWT.COLOR_RED));
}
});
ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.PRE_BUILD);
}
}
@Override
public void monitor(final Process process, ConsoleParser[] consoleParsers) throws IOException {
// console.clearConsole();
public void resourceChanged(IResourceChangeEvent event) {
switch (event.getType()) {
case IResourceChangeEvent.PRE_BUILD:
if (event.getBuildKind() != IncrementalProjectBuilder.AUTO_BUILD) {
// TODO this really should be done from the core and only when
// our projects are being built
console.clearConsole();
}
break;
}
}
public IFolder getBuildDirectory() {
return buildDirectory;
}
@Override
public void monitor(final Process process, ArduinoConsoleParser[] consoleParsers, IFolder buildDirectory)
throws IOException {
this.buildDirectory = buildDirectory;
// Clear the old listeners
for (ArduinoPatternMatchListener listener : listeners) {
console.removePatternMatchListener(listener);
}
listeners.clear();
// Add in the new ones if any
if (consoleParsers != null) {
for (ArduinoConsoleParser parser : consoleParsers) {
ArduinoPatternMatchListener listener;
if (parser instanceof ArduinoErrorParser) {
listener = new ArduinoErrorMatchListener(this, (ArduinoErrorParser) parser);
} else {
continue;
}
listeners.add(listener);
console.addPatternMatchListener(listener);
}
}
console.activate();
final Semaphore sema = new Semaphore(-1);

View file

@ -0,0 +1,30 @@
package org.eclipse.cdt.arduino.ui.internal.launch;
import org.eclipse.cdt.arduino.core.internal.console.ArduinoErrorParser;
import org.eclipse.cdt.arduino.ui.internal.Activator;
import org.eclipse.core.resources.IMarker;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.ui.console.PatternMatchEvent;
public class ArduinoErrorMatchListener extends ArduinoPatternMatchListener {
public ArduinoErrorMatchListener(ArduinoConsole arduinoConsole, ArduinoErrorParser parser) {
super(arduinoConsole, parser);
}
@Override
public void matchFound(PatternMatchEvent event) {
try {
String text = textConsole.getDocument().get(event.getOffset(), event.getLength());
IMarker marker = ((ArduinoErrorParser) parser).generateMarker(arduinoConsole.getBuildDirectory(), text);
if (marker != null) {
textConsole.addHyperlink(new ArduinoHyperlink(marker),
event.getOffset() + marker.getAttribute(ArduinoErrorParser.LINK_OFFSET, 0),
marker.getAttribute(ArduinoErrorParser.LINK_LENGTH, event.getLength()));
}
} catch (BadLocationException e) {
Activator.log(e);
}
}
}

View file

@ -0,0 +1,37 @@
package org.eclipse.cdt.arduino.ui.internal.launch;
import org.eclipse.cdt.arduino.ui.internal.Activator;
import org.eclipse.core.resources.IMarker;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.IHyperlink;
import org.eclipse.ui.ide.IDE;
public class ArduinoHyperlink implements IHyperlink {
private final IMarker marker;
public ArduinoHyperlink(IMarker marker) {
this.marker = marker;
}
@Override
public void linkEntered() {
}
@Override
public void linkExited() {
}
@Override
public void linkActivated() {
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
try {
IDE.openEditor(page, marker);
} catch (PartInitException e) {
Activator.log(e);
}
}
}

View file

@ -0,0 +1,43 @@
package org.eclipse.cdt.arduino.ui.internal.launch;
import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleParser;
import org.eclipse.ui.console.IPatternMatchListener;
import org.eclipse.ui.console.TextConsole;
public abstract class ArduinoPatternMatchListener implements IPatternMatchListener {
protected final ArduinoConsole arduinoConsole;
protected final ArduinoConsoleParser parser;
protected TextConsole textConsole;
public ArduinoPatternMatchListener(ArduinoConsole arduinoConsole, ArduinoConsoleParser parser) {
this.arduinoConsole = arduinoConsole;
this.parser = parser;
}
@Override
public void connect(TextConsole console) {
this.textConsole = console;
}
@Override
public void disconnect() {
}
@Override
public String getPattern() {
return parser.getPattern();
}
@Override
public int getCompilerFlags() {
return parser.getCompilerFlags();
}
@Override
public String getLineQualifier() {
return parser.getLineQualifier();
}
}