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:
parent
f635f6c7d8
commit
81f6bd0259
11 changed files with 311 additions and 33 deletions
|
@ -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();
|
||||
}
|
||||
} };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue