1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 17:35:35 +02:00

Bug 321443 - First implementation of new build model.

Includes adaptation of the Arduino build model where many of these
ideas started to the new model. And start of the Qt build system which
uses it.

Change-Id: Icb212185773ebc4d415e8a9862101744703ff80b
This commit is contained in:
Doug Schaefer 2015-08-31 11:26:50 -04:00 committed by Gerrit Code Review @ Eclipse.org
parent f505c21a48
commit 64c5782589
39 changed files with 1658 additions and 1007 deletions

View file

@ -2,12 +2,13 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.core; singleton:=true
Bundle-Version: 5.11.0.qualifier
Bundle-Version: 5.12.0.qualifier
Bundle-Activator: org.eclipse.cdt.core.CCorePlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.cdt.core,
org.eclipse.cdt.core.browser,
org.eclipse.cdt.core.build,
org.eclipse.cdt.core.cdtvariables,
org.eclipse.cdt.core.dom,
org.eclipse.cdt.core.dom.ast,
@ -73,7 +74,11 @@ Export-Package: org.eclipse.cdt.core,
org.eclipse.cdt.internal.core.indexer;x-internal:=true,
org.eclipse.cdt.internal.core.language;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.language.settings.providers;x-internal:=true,
org.eclipse.cdt.internal.core.model;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.debug.core,org.eclipse.cdt.debug.ui,org.eclipse.cdt.codan.ui",
org.eclipse.cdt.internal.core.model;
x-friends:="org.eclipse.cdt.ui,
org.eclipse.cdt.debug.core,
org.eclipse.cdt.debug.ui,
org.eclipse.cdt.codan.ui",
org.eclipse.cdt.internal.core.model.ext;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.parser;x-internal:=true,
org.eclipse.cdt.internal.core.parser.problem;x-internal:=true,
@ -122,6 +127,7 @@ Require-Bundle: org.eclipse.cdt.core.native;bundle-version="[5.7.0,6.0.0)";visib
org.eclipse.core.variables;bundle-version="[3.1.100,4.0.0)",
org.eclipse.ltk.core.refactoring;bundle-version="3.4.0",
org.eclipse.text;bundle-version="[3.2.0,4.0.0)",
com.ibm.icu;bundle-version="4.4.2"
com.ibm.icu;bundle-version="4.4.2",
com.google.gson;bundle-version="2.2.4"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7

View file

@ -683,6 +683,7 @@
<extension-point id="LanguageSettingsProvider" name="%LanguageSettingsProvider.name" schema="schema/LanguageSettingsProvider.exsd"/>
<extension-point id="UNCPathConverter" name="%uncPathConverter.name" schema="schema/UNCPathConverter.exsd"/>
<extension-point id="ProblemMarkerFilter" name="%problemMarkerFilter.name" schema="schema/ProblemMarkerFilter.exsd"/>
<extension-point id="ToolChain" name="ToolChain" schema="schema/ToolChain.exsd"/>
<extension
point="org.eclipse.cdt.core.templateProcessTypes">
@ -856,5 +857,22 @@
ordering="first">
</filterMatcher>
</extension>
<extension
point="org.eclipse.cdt.core.ToolChain">
<toolChain
adaptor="org.eclipse.cdt.core.build.GCCToolChain"
id="org.eclipse.cdt.core.gcc">
</toolChain>
</extension>
<extension
point="org.eclipse.core.runtime.adapters">
<factory
adaptableType="org.eclipse.cdt.core.build.CBuildConfiguration"
class="org.eclipse.cdt.core.build.GCCToolChain$Factory">
<adapter
type="org.eclipse.cdt.core.build.GCCToolChain">
</adapter>
</factory>
</extension>
</plugin>

View file

@ -11,7 +11,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<version>5.11.0-SNAPSHOT</version>
<version>5.12.0-SNAPSHOT</version>
<artifactId>org.eclipse.cdt.core</artifactId>
<packaging>eclipse-plugin</packaging>
</project>

View file

@ -1,10 +1,10 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.arduino.core" xmlns="http://www.w3.org/2001/XMLSchema">
<schema targetNamespace="org.eclipse.cdt.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appinfo>
<meta.schema plugin="org.eclipse.cdt.arduino.core" id="consoleService" name="Arduino Launch Console Service"/>
</appinfo>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.core" id="ToolChain" name="ToolChain"/>
</appInfo>
<documentation>
[Enter description of this extension point.]
</documentation>
@ -12,13 +12,13 @@
<element name="extension">
<annotation>
<appinfo>
<appInfo>
<meta.element />
</appinfo>
</appInfo>
</annotation>
<complexType>
<sequence>
<element ref="provider"/>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="toolChain"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
@ -39,60 +39,72 @@
<documentation>
</documentation>
<appinfo>
<appInfo>
<meta.attribute translatable="true"/>
</appinfo>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="provider">
<element name="toolChain">
<annotation>
<documentation>
A toolchain that implements the CToolChain interface and identified with the id attribute.
</documentation>
</annotation>
<complexType>
<attribute name="class" type="string" use="required">
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
id for the toolchain.
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.arduino.core.internal.launch.ArduinoLaunchConsoleService"/>
</appinfo>
</annotation>
</attribute>
<attribute name="adaptor" type="string" use="required">
<annotation>
<documentation>
The adaptor class for the toolchain. This is passed to getAdaptor on the CBuildConfiguration object.
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn="org.eclipse.cdt.core.build.CToolChain:"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appinfo>
<appInfo>
<meta.section type="since"/>
</appinfo>
</appInfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appinfo>
<appInfo>
<meta.section type="examples"/>
</appinfo>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<appInfo>
<meta.section type="apiinfo"/>
</appinfo>
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<appInfo>
<meta.section type="implementation"/>
</appinfo>
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>

View file

@ -0,0 +1,139 @@
package org.eclipse.cdt.core.build;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.osgi.service.prefs.BackingStoreException;
/**
* Root class for CDT build configurations. Provides access to the build
* settings for subclasses.
*
* @since 5.12
*/
public abstract class CBuildConfiguration extends PlatformObject {
private static final String TOOLCHAIN = "cdt.toolChain"; //$NON-NLS-1$
private final IBuildConfiguration config;
private CToolChain toolChain;
protected CBuildConfiguration(IBuildConfiguration config) {
this.config = config;
}
public IBuildConfiguration getBuildConfiguration() {
return config;
}
public String getName() {
return config.getName();
}
public IProject getProject() {
return config.getProject();
}
public void setActive(IProgressMonitor monitor) throws CoreException {
IProject project = config.getProject();
if (config.equals(project.getActiveBuildConfig())) {
// already set
return;
}
IProjectDescription projectDesc = project.getDescription();
projectDesc.setActiveBuildConfig(config.getName());
project.setDescription(projectDesc, monitor);
}
protected IEclipsePreferences getSettings() {
return (IEclipsePreferences) new ProjectScope(config.getProject()).getNode("org.eclipse.cdt.core") //$NON-NLS-1$
.node("config") //$NON-NLS-1$
.node(config.getName());
}
private synchronized CToolChain getToolChain(String id) throws CoreException {
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint point = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID + ".ToolChain"); //$NON-NLS-1$
for (IExtension extension : point.getExtensions()) {
for (IConfigurationElement element : extension.getConfigurationElements()) {
String eid = element.getAttribute("id"); //$NON-NLS-1$
if (id.equals(eid)) {
String clsName = element.getAttribute("adaptor"); //$NON-NLS-1$
if (clsName != null) {
try {
Class<?> cls = Class.forName(clsName);
return (CToolChain) getAdapter(cls);
} catch (ClassNotFoundException e) {
throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID,
"creating toolchain", e)); //$NON-NLS-1$
}
}
}
}
}
return null;
}
public synchronized void setToolChain(String id) throws CoreException {
CToolChain newtc = getToolChain(id);
if (newtc == null) {
throw new CoreException(
new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "unknown toolchain: " + id)); //$NON-NLS-1$
}
IEclipsePreferences settings = getSettings();
settings.put(TOOLCHAIN, id);
try {
settings.flush();
} catch (BackingStoreException e) {
throw new CoreException(
new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "saving toolchain id", e)); //$NON-NLS-1$
}
toolChain = newtc;
}
public CToolChain getToolChain() throws CoreException {
if (toolChain == null) {
IEclipsePreferences settings = getSettings();
String id = settings.get(TOOLCHAIN, ""); //$NON-NLS-1$
if (id.isEmpty()) {
return null;
} else {
toolChain = getToolChain(id);
}
}
return toolChain;
}
public IScannerInfo getScannerInfo(IResource resource) throws CoreException {
// By default, get it from the toolchain.
CToolChain toolChain = getToolChain();
return toolChain != null ? toolChain.getScannerInfo(resource) : null;
}
public void clearScannerInfo() throws CoreException {
}
public CConsoleParser[] getConsoleParsers() throws CoreException {
CToolChain toolChain = getToolChain();
return toolChain != null ? toolChain.getConsoleParsers() : null;
}
}

View file

@ -0,0 +1,121 @@
package org.eclipse.cdt.core.build;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.CCorePlugin;
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;
/**
* This could be temporary. Provides a core parser for the TextConsole's
* IPatternMatchListener.
*
* TODO that framework doesn't work well for builds that need to use different
* parsers at different times. Should consider taking that architecture and
* making it work well for our needs.
*
* @since 5.12
*/
public abstract class CConsoleParser {
private final String pattern;
private final int flags;
private final String lineQualifier;
private final Pattern errorPattern;
public static final String LINK_OFFSET = "cdt.link.offset"; //$NON-NLS-1$
public static final String LINK_LENGTH = "cdt.link.length"; //$NON-NLS-1$
protected CConsoleParser(String pattern, int flags, String lineQualifier) {
this.pattern = pattern;
this.flags = flags;
this.lineQualifier = lineQualifier;
this.errorPattern = Pattern.compile(pattern);
}
protected CConsoleParser(String pattern) {
this(pattern, 0, null);
}
/**
* Returns the pattern to be used for matching. The pattern is a string
* representing a regular expression.
*
* @return the regular expression to be used for matching
*/
public String getPattern() {
return pattern;
}
/**
* Returns the flags to use when compiling this pattern match listener's
* regular expression, as defined by by
* <code>Pattern.compile(String regex, int flags)</code>
*
* @return the flags to use when compiling this pattern match listener's
* regular expression
* @see java.util.regex.Pattern#compile(java.lang.String, int)
*/
public int getCompilerFlags() {
return flags;
}
/**
* Returns a simple regular expression used to identify lines that may match
* this pattern matcher's complete pattern, or <code>null</code>. Use of
* this attribute can improve performance by disqualifying lines from the
* search. When a line is found containing a match for this expression, the
* line is searched from the beginning for this pattern matcher's complete
* pattern. Lines not containing this pattern are discarded.
*
* @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() {
return lineQualifier;
}
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) {
CCorePlugin.log(e);
return null;
}
}
}
return null;
}
}

View file

@ -0,0 +1,119 @@
package org.eclipse.cdt.core.build;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.internal.core.build.ScannerInfoData;
import org.eclipse.cdt.internal.core.build.ToolChainScannerInfo;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.PlatformObject;
/**
* Root class for CDT toolchains.
*
* @since 5.12
*/
public abstract class CToolChain extends PlatformObject {
private final CBuildConfiguration config;
private ScannerInfoData scannerInfo;
protected CToolChain(CBuildConfiguration config) {
this.config = config;
}
public static String[] splitCommand(String command) {
// TODO deal with quotes properly, for now just strip
return command.replace("\"", "").split("\\s+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public CBuildConfiguration getBuildConfiguration() {
return config;
}
/**
* Update the given environment to run the toolchain.
*
* @param env
*/
public void setEnvironment(Map<String, String> env) {
// default, nothing
}
/**
* Scan the commandLine and save the scanner info for the resource being
* built, or if perProject is true, for all resources in the project. The
* buildFolder to help find the resource is where the command ran.
*
* @param buildFolder
* @param commandLine
* @throws CoreException
*/
public void scanBuildOutput(IFolder buildFolder, String commandLine, boolean perProject)
throws CoreException {
// default, nothing
}
protected void putScannerInfo(IResource resource, Map<String, String> definedSymbols,
List<String> includePaths, List<String> macroFiles, List<String> includeFiles,
List<String> localIncludePath) throws CoreException {
if (scannerInfo == null) {
loadScannerInfo();
}
scannerInfo.putScannerInfo(resource, new ToolChainScannerInfo(definedSymbols, includePaths,
macroFiles, includeFiles, localIncludePath));
}
protected void putScannerInfo(ILanguage language, Map<String, String> definedSymbols,
List<String> includePaths, List<String> macroFiles, List<String> includeFiles,
List<String> localIncludePath) throws CoreException {
if (scannerInfo == null) {
loadScannerInfo();
}
scannerInfo.putScannerInfo(language, new ToolChainScannerInfo(definedSymbols, includePaths,
macroFiles, includeFiles, localIncludePath));
}
private void loadScannerInfo() {
if (scannerInfo == null) {
scannerInfo = ScannerInfoData.load(this);
}
}
/**
* Return the scanner info for the given resource.
*
* @param resource
* @return scanner info for the resource
* @throws CoreException
*/
public IScannerInfo getScannerInfo(IResource resource) throws CoreException {
loadScannerInfo();
return scannerInfo.getScannerInfo(resource);
}
public void clearScannerInfo() throws CoreException {
if (scannerInfo == null) {
scannerInfo = new ScannerInfoData();
scannerInfo.queueSave();
} else {
scannerInfo.clear();
}
}
/**
* Return the console parsers to be used when this toolchain is being used
* for a build.
*
* @return console parsers
*/
public CConsoleParser[] getConsoleParsers() {
return null;
}
}

View file

@ -0,0 +1,224 @@
package org.eclipse.cdt.core.build;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.LanguageManager;
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.runtime.CoreException;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
/**
* The GCC toolchain. Placing it in cdt.core for now.
*
* TODO move to it's own plug-in.
*
* @since 5.12
*/
public class GCCToolChain extends CToolChain {
public static final String ID = "org.eclipse.cdt.core.gcc"; //$NON-NLS-1$
public GCCToolChain(CBuildConfiguration config) {
super(config);
}
private static Map<CBuildConfiguration, GCCToolChain> cache = new HashMap<>();
public static class Factory implements IAdapterFactory {
@SuppressWarnings("unchecked")
@Override
public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
if (adapterType.equals(GCCToolChain.class) && adaptableObject instanceof CBuildConfiguration) {
CBuildConfiguration config = (CBuildConfiguration) adaptableObject;
GCCToolChain toolChain = cache.get(config);
if (toolChain == null) {
toolChain = new GCCToolChain(config);
cache.put(config, toolChain);
}
return (T) toolChain;
}
return null;
}
@Override
public Class<?>[] getAdapterList() {
return new Class<?>[] { GCCToolChain.class };
}
}
@Override
public void scanBuildOutput(IFolder buildFolder, String commandLine, boolean perProject)
throws CoreException {
try {
if (Platform.getOS().equals(Platform.OS_WIN32)) {
// Need to flip over the slashes on Windows
commandLine = commandLine.replace('\\', '/');
}
String[] command = splitCommand(commandLine);
// Change output to stdout
for (int i = 0; i < command.length - 1; ++i) {
if (command[i].equals("-o")) { //$NON-NLS-1$
command[i + 1] = "-"; //$NON-NLS-1$
break;
}
}
// Change source file to a tmp file (needs to be empty)
Path tmpFile = null;
IFile file = null;
for (int i = 1; i < command.length; ++i) {
if (!command[i].startsWith("-")) { //$NON-NLS-1$
// TODO optimize by dealing with multi arg options like -o
IFile f = buildFolder.getFile(command[i]);
if (f.exists() && CoreModel.isTranslationUnit(f)) {
// replace it with a temp file
Path parentPath = new File(((IFolder) f.getParent()).getLocationURI()).toPath();
int n = 0;
while (true) {
tmpFile = parentPath.resolve(".sc" + n + "." + f.getFileExtension()); //$NON-NLS-1$ //$NON-NLS-2$
command[i] = tmpFile.toString();
try {
Files.createFile(tmpFile);
break;
} catch (FileAlreadyExistsException e) {
// try again
++n;
}
}
file = f;
break;
}
}
}
if (file == null) {
// can't do much without the source file
CCorePlugin.log("No source file for scanner discovery"); //$NON-NLS-1$
return;
}
// Add in the magic potion: -E -P -v -dD
String[] fullCmd = new String[command.length + 4];
fullCmd[0] = command[0];
fullCmd[1] = "-E"; //$NON-NLS-1$
fullCmd[2] = "-P"; //$NON-NLS-1$
fullCmd[3] = "-v"; //$NON-NLS-1$
fullCmd[4] = "-dD"; //$NON-NLS-1$
System.arraycopy(command, 1, fullCmd, 5, command.length - 1);
File buildDir = new File(buildFolder.getLocationURI());
Files.createDirectories(buildDir.toPath());
// Startup the command
ProcessBuilder processBuilder = new ProcessBuilder(fullCmd).directory(buildDir)
.redirectErrorStream(true);
setEnvironment(processBuilder.environment());
Process process = processBuilder.start();
// Scan for the scanner info
Map<String, String> symbols = new HashMap<>();
List<String> includePath = new ArrayList<>();
Pattern definePattern = Pattern.compile("#define (.*)\\s(.*)"); //$NON-NLS-1$
boolean inIncludePaths = false;
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
if (inIncludePaths) {
if (line.equals("End of search list.")) { //$NON-NLS-1$
inIncludePaths = false;
} else {
includePath.add(line.trim());
}
} else if (line.startsWith("#define ")) { //$NON-NLS-1$
Matcher matcher = definePattern.matcher(line);
if (matcher.matches()) {
symbols.put(matcher.group(1), matcher.group(2));
}
} else if (line.equals("#include <...> search starts here:")) { //$NON-NLS-1$
inIncludePaths = true;
}
}
}
if (perProject) {
IProject project = buildFolder.getProject();
IContentType contentType = CCorePlugin.getContentType(project, file.getName());
if (contentType != null) {
ILanguage language = LanguageManager.getInstance().getLanguage(contentType, project);
putScannerInfo(language, symbols, includePath, null, null, null);
}
} else {
putScannerInfo(file, symbols, includePath, null, null, null);
}
if (tmpFile != null) {
Files.delete(tmpFile);
}
} catch (IOException e) {
throw new CoreException(
new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Scanning build output", e)); //$NON-NLS-1$
}
}
@Override
public CConsoleParser[] getConsoleParsers() {
// ../src/Test.cpp:4:1: error: 'x' was not declared in this scope
return new CConsoleParser[] { new CConsoleParser("(.*?):(\\d+):(\\d+:)? (fatal )?error: (.*)") { //$NON-NLS-1$
@Override
protected int getSeverity(Matcher matcher) {
return IMarker.SEVERITY_ERROR;
}
@Override
protected String getMessage(Matcher matcher) {
return matcher.group(5);
}
@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

@ -0,0 +1,45 @@
package org.eclipse.cdt.core.build;
import java.io.IOException;
import org.eclipse.core.resources.IFolder;
/**
* This may be temporary. It's uses the TextConsole's parsing and hyperlink
* framework to parse build output for errors.
*
* TODO Should we replace all CDT build consoles with this.
*
* @since 5.12
*/
public interface IConsoleService {
/**
* Display the stdout and stderr of the process in the console. Use the
* console parsers to parse that output to mark errors and warnings and
* such. The build directory helps to find resources for markers.
*
* @param process
* @param consoleParsers
* @param buildDirectory
* @throws IOException
*/
void monitor(Process process, CConsoleParser[] consoleParsers, IFolder buildDirectory) throws IOException;
/**
* Write a message on the console stdout.
*
* @param msg
* @throws IOException
*/
void writeOutput(String msg) throws IOException;
/**
* Write a message on the console stderr.
*
* @param msg
* @throws IOException
*/
void writeError(String msg) throws IOException;
}

View file

@ -0,0 +1,166 @@
package org.eclipse.cdt.internal.core.build;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.build.CBuildConfiguration;
import org.eclipse.cdt.core.build.CToolChain;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import com.google.gson.Gson;
public class ScannerInfoData {
private Set<ToolChainScannerInfo> perResourceInfo;
private Map<String, ToolChainScannerInfo> perLanguageInfo;
private transient Path savePath;
private transient Map<ToolChainScannerInfo, ToolChainScannerInfo> infoCache;
private transient Map<String, ToolChainScannerInfo> resourceCache;
public void createCache() {
infoCache = new HashMap<>();
resourceCache = new HashMap<>();
if (perResourceInfo != null) {
for (ToolChainScannerInfo info : perResourceInfo) {
infoCache.put(info, info);
for (String path : info.getResourcePaths()) {
resourceCache.put(path, info);
}
}
}
}
private boolean perResource() {
return perResourceInfo != null && !perResourceInfo.isEmpty();
}
private boolean perLanguage() {
return perLanguageInfo != null && !perLanguageInfo.isEmpty();
}
public IScannerInfo getScannerInfo(IResource resource) {
if (perResource()) {
ToolChainScannerInfo info = resourceCache.get(resource.getFullPath().toString());
if (info != null) {
return info.getScannerInfo();
}
}
// Else try language
if (perLanguage()) {
IProject project = resource.getProject();
IContentType contentType = CCorePlugin.getContentType(project, resource.getName());
if (contentType != null) {
ILanguage language = LanguageManager.getInstance().getLanguage(contentType, project);
ToolChainScannerInfo info = perLanguageInfo.get(language.getId());
if (info != null) {
return info.getScannerInfo();
}
}
}
return null;
}
public IScannerInfo getScannerInfo(ILanguage language) {
if (perLanguage()) {
ToolChainScannerInfo info = perLanguageInfo.get(language.getId());
if (info != null) {
return info.getScannerInfo();
}
}
return null;
}
public void putScannerInfo(IResource resource, ToolChainScannerInfo info) {
if (perResourceInfo == null) {
perResourceInfo = new HashSet<>();
infoCache = new HashMap<>();
infoCache.put(info, info);
} else {
ToolChainScannerInfo existing = infoCache.get(info);
if (existing != null) {
info = existing;
} else {
perResourceInfo.add(info);
infoCache.put(info, info);
}
}
info.addResource(resource);
resourceCache.put(resource.getFullPath().toString(), info);
queueSave();
}
public void putScannerInfo(ILanguage language, ToolChainScannerInfo info) {
if (perLanguageInfo == null) {
perLanguageInfo = new HashMap<>();
}
perLanguageInfo.put(language.getId(), info);
queueSave();
}
public static ScannerInfoData load(CToolChain toolChain) {
IPath stateLoc = Platform.getStateLocation(CCorePlugin.getDefault().getBundle());
CBuildConfiguration config = toolChain.getBuildConfiguration();
IPath scannerInfoPath = stateLoc.append(config.getProject().getName())
.append(config.getName() + ".scInfo"); //$NON-NLS-1$
File scannerInfoFile = scannerInfoPath.toFile();
ScannerInfoData info = null;
if (scannerInfoFile.canRead()) {
try (Reader reader = new FileReader(scannerInfoFile)) {
info = new Gson().fromJson(reader, ScannerInfoData.class);
} catch (Exception e) {
CCorePlugin.log(e);
}
}
if (info == null) {
info = new ScannerInfoData();
}
info.savePath = scannerInfoFile.toPath();
info.createCache();
return info;
}
public void save() {
try {
String json = new Gson().toJson(this);
Files.createDirectories(savePath.getParent());
Files.write(savePath, json.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
CCorePlugin.log(e);
}
}
public void queueSave() {
ScannerInfoSaveParticipant.getInstance().save(this);
}
public void clear() {
perLanguageInfo = null;
perResourceInfo = null;
createCache();
queueSave();
}
}

View file

@ -0,0 +1,50 @@
package org.eclipse.cdt.internal.core.build;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.ISaveContext;
import org.eclipse.core.resources.ISaveParticipant;
import org.eclipse.core.runtime.CoreException;
public class ScannerInfoSaveParticipant implements ISaveParticipant {
private static ScannerInfoSaveParticipant instance;
private Set<ScannerInfoData> toBeSaved = new HashSet<>();
public ScannerInfoSaveParticipant() {
assert instance == null;
instance = this;
}
public static ScannerInfoSaveParticipant getInstance() {
return instance;
}
public void save(ScannerInfoData info) {
toBeSaved.add(info);
}
@Override
public void doneSaving(ISaveContext context) {
}
@Override
public void prepareToSave(ISaveContext context) throws CoreException {
}
@Override
public void rollback(ISaveContext context) {
// TODO Auto-generated method stub
}
@Override
public void saving(ISaveContext context) throws CoreException {
for (ScannerInfoData info : toBeSaved) {
info.save();
}
toBeSaved.clear();
}
}

View file

@ -0,0 +1,56 @@
package org.eclipse.cdt.internal.core.build;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.core.resources.IResource;
public class ToolChainScannerInfo {
private Map<String, String> definedSymbols;
private List<String> includePaths;
private List<String> macroFiles;
private List<String> includeFiles;
private List<String> localIncludePath;
private Set<String> resourcePaths;
private transient IScannerInfo scannerInfo;
public ToolChainScannerInfo(Map<String, String> definedSymbols, List<String> includePaths,
List<String> macroFiles, List<String> includeFiles, List<String> localIncludePath) {
this.definedSymbols = definedSymbols;
this.includePaths = includePaths;
this.macroFiles = macroFiles;
this.includeFiles = includeFiles;
this.localIncludePath = localIncludePath;
}
public IScannerInfo getScannerInfo() {
if (scannerInfo == null) {
scannerInfo = new ExtendedScannerInfo(definedSymbols,
includePaths != null ? includePaths.toArray(new String[includePaths.size()]) : null,
macroFiles != null ? macroFiles.toArray(new String[includePaths.size()]) : null,
includeFiles != null ? includeFiles.toArray(new String[includePaths.size()]) : null,
localIncludePath != null ? localIncludePath.toArray(new String[includePaths.size()])
: null);
}
return scannerInfo;
}
public Collection<String> getResourcePaths() {
return resourcePaths != null ? resourcePaths : Collections.<String> emptySet();
}
public void addResource(IResource resource) {
if (resourcePaths == null) {
resourcePaths = new HashSet<>();
}
resourcePaths.add(resource.getFullPath().toString());
}
}

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.ui; singleton:=true
Bundle-Version: 5.11.0.qualifier
Bundle-Version: 5.12.0.qualifier
Bundle-Activator: org.eclipse.cdt.ui.CUIPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@ -126,3 +126,4 @@ Require-Bundle: org.eclipse.cdt.core;bundle-version="[5.2.0,6.0.0)",
org.eclipse.e4.ui.css.swt.theme
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Service-Component: OSGI-INF/consoleservice.xml

View file

@ -0,0 +1,6 @@
<component name="QtConsoleService">
<implementation class="org.eclipse.cdt.internal.ui.build.CConsoleService"/>
<service>
<provide interface="org.eclipse.cdt.core.build.IConsoleService"/>
</service>
</component>

View file

@ -11,7 +11,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<version>5.11.0-SNAPSHOT</version>
<version>5.12.0-SNAPSHOT</version>
<artifactId>org.eclipse.cdt.ui</artifactId>
<packaging>eclipse-plugin</packaging>
</project>

View file

@ -1,12 +1,13 @@
package org.eclipse.cdt.internal.qt.ui;
package org.eclipse.cdt.internal.ui.build;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.eclipse.cdt.internal.qt.core.QtPlugin;
import org.eclipse.cdt.internal.qt.core.build.IConsoleService;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IncrementalProjectBuilder;
@ -18,14 +19,21 @@ import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;
public class QtConsoleService implements IConsoleService, IResourceChangeListener {
import org.eclipse.cdt.core.build.CConsoleParser;
import org.eclipse.cdt.core.build.IConsoleService;
import org.eclipse.cdt.ui.CUIPlugin;
public class CConsoleService implements IConsoleService, IResourceChangeListener {
private MessageConsole console;
private MessageConsoleStream out;
private MessageConsoleStream err;
private IFolder buildDirectory;
List<CPatternMatchListener> listeners = new ArrayList<>();
private void initConsole() {
console = new MessageConsole("Qt Builds", null);
console = new MessageConsole("C/C++", null);
ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { console });
out = console.newMessageStream();
err = console.newMessageStream();
@ -57,19 +65,39 @@ public class QtConsoleService implements IConsoleService, IResourceChangeListene
}
@Override
public void monitor(final Process process) throws IOException {
public void monitor(final Process process, CConsoleParser[] consoleParsers, IFolder buildDirectory)
throws IOException {
if (console == null) {
initConsole();
}
this.buildDirectory = buildDirectory;
// Clear the old listeners
for (CPatternMatchListener listener : listeners) {
console.removePatternMatchListener(listener);
}
listeners.clear();
// Add in the new ones if any
if (consoleParsers != null) {
for (CConsoleParser parser : consoleParsers) {
CPatternMatchListener listener = new CPatternMatchListener(this, parser);
listeners.add(listener);
console.addPatternMatchListener(listener);
}
}
console.activate();
final CountDownLatch latch = new CountDownLatch(2);
// Output stream reader
new Thread("Qt Build Console Output") {
new Thread("C/C++ Build Console Output") { //$NON-NLS-1$
@Override
public void run() {
try (BufferedReader processOut = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
try (BufferedReader processOut = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
for (String line = processOut.readLine(); line != null; line = processOut.readLine()) {
out.write(line);
out.write('\n');
@ -83,9 +111,11 @@ public class QtConsoleService implements IConsoleService, IResourceChangeListene
}.start();
// Error stream reader
new Thread("Qt Build Console Error") {
new Thread("C/C++ Build Console Error") { //$NON-NLS-1$
@Override
public void run() {
try (BufferedReader processErr = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
try (BufferedReader processErr = new BufferedReader(
new InputStreamReader(process.getErrorStream()))) {
for (String line = processErr.readLine(); line != null; line = processErr.readLine()) {
err.write(line);
out.write('\n');
@ -102,7 +132,7 @@ public class QtConsoleService implements IConsoleService, IResourceChangeListene
latch.await();
process.waitFor();
} catch (InterruptedException e) {
QtPlugin.log(e);
CUIPlugin.log(e);
}
}
@ -122,4 +152,8 @@ public class QtConsoleService implements IConsoleService, IResourceChangeListene
err.write(msg);
}
public IFolder getBuildDirectory() {
return buildDirectory;
}
}

View file

@ -1,6 +1,5 @@
package org.eclipse.cdt.arduino.ui.internal.launch;
package org.eclipse.cdt.internal.ui.build;
import org.eclipse.cdt.arduino.ui.internal.Activator;
import org.eclipse.core.resources.IMarker;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
@ -8,11 +7,13 @@ import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.IHyperlink;
import org.eclipse.ui.ide.IDE;
public class ArduinoHyperlink implements IHyperlink {
import org.eclipse.cdt.ui.CUIPlugin;
public class CHyperlink implements IHyperlink {
private final IMarker marker;
public ArduinoHyperlink(IMarker marker) {
public CHyperlink(IMarker marker) {
this.marker = marker;
}
@ -30,7 +31,7 @@ public class ArduinoHyperlink implements IHyperlink {
try {
IDE.openEditor(page, marker);
} catch (PartInitException e) {
Activator.log(e);
CUIPlugin.log(e);
}
}

View file

@ -0,0 +1,63 @@
package org.eclipse.cdt.internal.ui.build;
import org.eclipse.core.resources.IMarker;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.ui.console.IPatternMatchListener;
import org.eclipse.ui.console.PatternMatchEvent;
import org.eclipse.ui.console.TextConsole;
import org.eclipse.cdt.core.build.CConsoleParser;
import org.eclipse.cdt.ui.CUIPlugin;
public class CPatternMatchListener implements IPatternMatchListener {
protected final CConsoleService console;
protected final CConsoleParser parser;
protected TextConsole textConsole;
public CPatternMatchListener(CConsoleService console, CConsoleParser parser) {
this.console = console;
this.parser = parser;
}
@Override
public void connect(TextConsole console) {
this.textConsole = console;
}
@Override
public void disconnect() {
}
@Override
public void matchFound(PatternMatchEvent event) {
try {
String text = textConsole.getDocument().get(event.getOffset(), event.getLength());
IMarker marker = parser.generateMarker(console.getBuildDirectory(), text);
if (marker != null) {
textConsole.addHyperlink(new CHyperlink(marker),
event.getOffset() + marker.getAttribute(CConsoleParser.LINK_OFFSET, 0),
marker.getAttribute(CConsoleParser.LINK_LENGTH, event.getLength()));
}
} catch (BadLocationException e) {
CUIPlugin.log(e);
}
}
@Override
public String getPattern() {
return parser.getPattern();
}
@Override
public int getCompilerFlags() {
return parser.getCompilerFlags();
}
@Override
public String getLineQualifier() {
return parser.getLineQualifier();
}
}

View file

@ -1,14 +0,0 @@
package org.eclipse.cdt.internal.qt.core.build;
import java.io.IOException;
public interface IConsoleService {
// TODO add error parsers
void monitor(Process process) throws IOException;
void writeOutput(String msg) throws IOException;
void writeError(String msg) throws IOException;
}

View file

@ -4,6 +4,7 @@ import java.io.File;
import java.io.IOException;
import java.util.Map;
import org.eclipse.cdt.core.build.IConsoleService;
import org.eclipse.cdt.internal.qt.core.QtPlugin;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@ -43,12 +44,12 @@ public class QtBuilder extends IncrementalProjectBuilder {
}
msg.append('\n');
console.writeOutput(msg.toString());
console.monitor(process);
console.monitor(process, null, buildFolder);
}
// run make
Process process = new ProcessBuilder("make").directory(new File(buildFolder.getLocationURI())).start(); //$NON-NLS-1$
console.monitor(process);
console.monitor(process, null, buildFolder);
buildFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor);
return new IProject[] { project };

View file

@ -20,4 +20,3 @@ Require-Bundle: org.eclipse.core.runtime,
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.cdt.internal.qt.ui.assist;x-friends:="org.eclipse.cdt.qt.tests"
Service-Component: OSGI-INF/consoleservice.xml

View file

@ -1,6 +0,0 @@
<component name="QtConsoleService">
<implementation class="org.eclipse.cdt.internal.qt.ui.QtConsoleService"/>
<service>
<provide interface="org.eclipse.cdt.internal.qt.core.build.IConsoleService"/>
</service>
</component>

View file

@ -44,9 +44,6 @@ public class QtUIPlugin extends AbstractUIPlugin {
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
// context.registerService(IConsoleService.class, new
// QtConsoleService(), null);
}
@Override

View file

@ -22,6 +22,5 @@ Bundle-ClassPath: libs/freemarker-2.3.22.jar,
Export-Package: org.eclipse.cdt.arduino.core.internal;x-friends:="org.eclipse.cdt.arduino.ui",
org.eclipse.cdt.arduino.core.internal.board;x-friends:="org.eclipse.cdt.arduino.ui",
org.eclipse.cdt.arduino.core.internal.build;x-friends:="org.eclipse.cdt.arduino.ui",
org.eclipse.cdt.arduino.core.internal.console;x-friends:="org.eclipse.cdt.arduino.ui",
org.eclipse.cdt.arduino.core.internal.remote;x-friends:="org.eclipse.cdt.arduino.ui"
Bundle-Localization: plugin

View file

@ -4,6 +4,5 @@ bin.includes = META-INF/,\
plugin.xml,\
templates/,\
about.html,\
schema/,\
plugin.properties,\
libs/

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension-point id="consoleService" name="Arduino Launch Console Service" schema="schema/consoleService.exsd"/>
<extension
point="org.eclipse.debug.core.launchConfigurationTypes">
<launchConfigurationType

View file

@ -10,12 +10,8 @@
*******************************************************************************/
package org.eclipse.cdt.arduino.core.internal;
import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleService;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.osgi.framework.BundleContext;
@ -59,10 +55,4 @@ public class Activator extends Plugin {
return ref != null ? context.getService(ref) : null;
}
public static ArduinoConsoleService getConsoleService() throws CoreException {
IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(Activator.getId(), "consoleService"); //$NON-NLS-1$
IExtension extension = point.getExtensions()[0]; // should only be one
return (ArduinoConsoleService) extension.getConfigurationElements()[0].createExecutableExtension("class"); //$NON-NLS-1$
}
}

View file

@ -195,7 +195,7 @@ public class ArduinoManager {
try {
for (IBuildConfiguration config : project.getBuildConfigs()) {
ArduinoBuildConfiguration arduinoConfig = config.getAdapter(ArduinoBuildConfiguration.class);
arduinoConfig.clearScannerInfoCache();
arduinoConfig.clearScannerInfo();
}
} catch (CoreException e) {
mstatus.add(e.getStatus());

View file

@ -1,11 +1,7 @@
package org.eclipse.cdt.arduino.core.internal.build;
import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
@ -15,8 +11,6 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.arduino.core.internal.Activator;
import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences;
@ -28,26 +22,24 @@ 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.build.CBuildConfiguration;
import org.eclipse.cdt.core.build.CToolChain;
import org.eclipse.cdt.core.build.GCCToolChain;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IOutputEntry;
import org.eclipse.cdt.core.model.IPathEntry;
import org.eclipse.cdt.core.model.ISourceRoot;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
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;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.core.runtime.IProgressMonitor;
@ -57,25 +49,29 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.osgi.service.prefs.BackingStoreException;
public class ArduinoBuildConfiguration {
public class ArduinoBuildConfiguration extends CBuildConfiguration {
private static final String PACKAGE_NAME = "packageName"; //$NON-NLS-1$
private static final String PLATFORM_NAME = "platformName"; //$NON-NLS-1$
private static final String BOARD_NAME = "boardName"; //$NON-NLS-1$
private final IBuildConfiguration config;
private ArduinoBoard board;
private Properties properties;
// Cache for scanner info
private IScannerInfo cScannerInfo;
private IScannerInfo cppScannerInfo;
private final static boolean isWindows = Platform.getOS().equals(Platform.OS_WIN32);
private ArduinoBuildConfiguration(IBuildConfiguration config) {
this.config = config;
super(config);
try {
if (getToolChain() == null) {
// For now, assume GCC is the toolchain,
// not sure it's ever not.
setToolChain(GCCToolChain.ID);
}
} catch (CoreException e) {
Activator.log(e);
}
}
private static Map<IBuildConfiguration, ArduinoBuildConfiguration> cache = new HashMap<>();
@ -135,23 +131,6 @@ public class ArduinoBuildConfiguration {
return arduinoConfig;
}
public void setActive(IProgressMonitor monitor) throws CoreException {
IProject project = config.getProject();
if (config.equals(project.getActiveBuildConfig())) {
// already set
return;
}
IProjectDescription projectDesc = project.getDescription();
projectDesc.setActiveBuildConfig(config.getName());
project.setDescription(projectDesc, monitor);
}
public IEclipsePreferences getSettings() {
return (IEclipsePreferences) new ProjectScope(config.getProject()).getNode(Activator.getId()).node("config") //$NON-NLS-1$
.node(config.getName());
}
public void setBoard(ArduinoBoard board) throws CoreException {
this.board = board;
@ -165,7 +144,7 @@ public class ArduinoBuildConfiguration {
try {
settings.flush();
} catch (BackingStoreException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Saving preferences", e));
throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Saving preferences", e)); //$NON-NLS-1$
}
}
@ -191,15 +170,15 @@ public class ArduinoBuildConfiguration {
}
properties.put("runtime.ide.version", "10607"); //$NON-NLS-1$ //$NON-NLS-2$
properties.put("build.arch", platform.getArchitecture().toUpperCase()); //$NON-NLS-1$
properties.put("build.path", config.getName()); //$NON-NLS-1$
properties.put("build.path", getName()); //$NON-NLS-1$
}
// always do this in case the project changes names
properties.put("build.project_name", config.getProject().getName()); //$NON-NLS-1$
properties.put("build.project_name", getProject().getName()); //$NON-NLS-1$
return properties;
}
public IFolder getBuildFolder() throws CoreException {
IProject project = config.getProject();
IProject project = getProject();
return project.getFolder("build"); //$NON-NLS-1$
}
@ -215,7 +194,7 @@ public class ArduinoBuildConfiguration {
}
public IFile generateMakeFile(IProgressMonitor monitor) throws CoreException {
final IProject project = config.getProject();
final IProject project = getProject();
IFolder buildFolder = getBuildFolder();
if (!buildFolder.exists()) {
@ -368,7 +347,7 @@ public class ArduinoBuildConfiguration {
List<Path> toolPaths = new ArrayList<>();
if (isWindows) {
// Add in the tools/make directory to pick up make
toolPaths.add(ArduinoPreferences.getArduinoHome().resolve("tools/make"));
toolPaths.add(ArduinoPreferences.getArduinoHome().resolve("tools/make")); //$NON-NLS-1$
}
ArduinoBoard board = getBoard();
ArduinoPlatform platform = board.getPlatform();
@ -444,57 +423,40 @@ public class ArduinoBuildConfiguration {
String command = resolveProperty("tools." + toolName + ".upload.pattern", properties); //$NON-NLS-1$ //$NON-NLS-2$
if (isWindows) {
return splitCommand(command);
return CToolChain.splitCommand(command);
} else {
return new String[] { "sh", "-c", command }; //$NON-NLS-1$ //$NON-NLS-2$
}
}
public IScannerInfo getScannerInfo(IResource resource) throws CoreException {
// what language is this resource and pick the right path;
switch (CCorePlugin.getContentType(resource.getProject(), resource.getName()).getId()) {
case CCorePlugin.CONTENT_TYPE_CXXSOURCE:
case CCorePlugin.CONTENT_TYPE_CXXHEADER:
if (cppScannerInfo == null) {
cppScannerInfo = calculateScannerInfo("recipe.cpp.o.pattern", resource); //$NON-NLS-1$
IScannerInfo info = super.getScannerInfo(resource);
if (info == null) {
// what language is this resource and pick the right recipe
String recipe;
switch (CCorePlugin.getContentType(resource.getProject(), resource.getName()).getId()) {
case CCorePlugin.CONTENT_TYPE_CXXSOURCE:
case CCorePlugin.CONTENT_TYPE_CXXHEADER:
recipe = "recipe.cpp.o.pattern"; //$NON-NLS-1$
break;
default:
recipe = "recipe.c.o.pattern"; //$NON-NLS-1$
}
return cppScannerInfo;
default:
if (cScannerInfo == null) {
cScannerInfo = calculateScannerInfo("recipe.c.o.pattern", resource); //$NON-NLS-1$
}
return cScannerInfo;
}
}
public void clearScannerInfoCache() {
cppScannerInfo = null;
cScannerInfo = null;
}
public static String pathString(Path path) {
String str = path.toString();
if (isWindows) {
str = str.replaceAll("\\\\", "/");
}
return str;
}
private IScannerInfo calculateScannerInfo(String recipe, IResource resource) throws CoreException {
try {
ArduinoPlatform platform = getBoard().getPlatform();
Properties properties = new Properties();
properties.putAll(getProperties());
Path tmpFile = Files.createTempFile("cdt", ".cpp"); //$NON-NLS-1$ //$NON-NLS-2$
properties.put("source_file", pathString(tmpFile)); //$NON-NLS-1$
Path resourcePath = new File(resource.getLocationURI()).toPath();
Path sourcePath = getBuildDirectory().toPath().relativize(resourcePath);
properties.put("source_file", pathString(sourcePath)); //$NON-NLS-1$
properties.put("object_file", "-"); //$NON-NLS-1$ //$NON-NLS-2$
String includes = "-E -P -v -dD"; //$NON-NLS-1$
String includes = ""; //$NON-NLS-1$
for (Path include : platform.getIncludePath()) {
includes += " -I\"" + pathString(include) + '"'; //$NON-NLS-1$
}
Collection<ArduinoLibrary> libs = ArduinoManager.instance.getLibraries(config.getProject());
Collection<ArduinoLibrary> libs = ArduinoManager.instance.getLibraries(getProject());
for (ArduinoLibrary lib : libs) {
for (Path path : lib.getIncludePath()) {
includes += " -I\"" + pathString(path) + '"'; //$NON-NLS-1$
@ -502,87 +464,18 @@ public class ArduinoBuildConfiguration {
}
properties.put("includes", includes); //$NON-NLS-1$
String[] command;
if (isWindows) {
command = splitCommand(resolveProperty(recipe, properties));
} else {
command = new String[] { "sh", "-c", resolveProperty(recipe, properties) }; //$NON-NLS-1$ //$NON-NLS-2$
}
ProcessBuilder processBuilder = new ProcessBuilder(command).directory(tmpFile.getParent().toFile())
.redirectErrorStream(true);
setEnvironment(processBuilder.environment());
Process process = processBuilder.start();
Map<String, String> symbols = new HashMap<>();
List<String> includePath = new ArrayList<>();
Pattern definePattern = Pattern.compile("#define (.*)\\s(.*)"); //$NON-NLS-1$
boolean inIncludePaths = false;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
if (inIncludePaths) {
if (line.equals("End of search list.")) { //$NON-NLS-1$
inIncludePaths = false;
} else {
includePath.add(line.trim());
}
} else if (line.startsWith("#define ")) { //$NON-NLS-1$
Matcher matcher = definePattern.matcher(line);
if (matcher.matches()) {
symbols.put(matcher.group(1), matcher.group(2));
}
} else if (line.equals("#include <...> search starts here:")) { //$NON-NLS-1$
inIncludePaths = true;
}
}
}
Files.delete(tmpFile);
ExtendedScannerInfo scannerInfo = new ExtendedScannerInfo(symbols,
includePath.toArray(new String[includePath.size()]));
return scannerInfo;
} catch (IOException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Compiler built-ins", e));
getToolChain().scanBuildOutput(getBuildFolder(), resolveProperty(recipe, properties), true);
info = super.getScannerInfo(resource);
}
return info;
}
private String[] splitCommand(String command) {
// TODO deal with quotes properly, for now just strip
return command.replaceAll("\"", "").split("\\s+");
}
public ArduinoConsoleParser[] getBuildConsoleParsers() {
// ../src/Test.cpp:4:1: error: 'x' was not declared in this scope
return new ArduinoConsoleParser[] { new ArduinoErrorParser("(.*?):(\\d+):(\\d+:)? (fatal )?error: (.*)") { //$NON-NLS-1$
@Override
protected int getSeverity(Matcher matcher) {
return IMarker.SEVERITY_ERROR;
}
@Override
protected String getMessage(Matcher matcher) {
return matcher.group(5);
}
@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();
}
} };
public static String pathString(Path path) {
String str = path.toString();
if (isWindows) {
str = str.replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
}
return str;
}
}

View file

@ -15,7 +15,7 @@ import java.util.regex.Matcher;
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.build.IConsoleService;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@ -39,8 +39,8 @@ public class ArduinoBuilder extends IncrementalProjectBuilder {
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()));
IConsoleService consoleService = Activator.getService(IConsoleService.class);
consoleService.writeOutput(String.format("Building %s\n", project.getName()));
ArduinoBuildConfiguration config = getBuildConfig().getAdapter(ArduinoBuildConfiguration.class);
config.generateMakeFile(monitor);
@ -50,15 +50,16 @@ public class ArduinoBuilder extends IncrementalProjectBuilder {
config.setEnvironment(processBuilder.environment());
Process process = processBuilder.start();
consoleService.monitor(process, config.getBuildConsoleParsers(), config.getBuildFolder());
consoleService.monitor(process, config.getConsoleParsers(), config.getBuildFolder());
if (process.exitValue() == 0) {
showSizes(config, consoleService);
}
config.getBuildFolder().refreshLocal(IResource.DEPTH_INFINITE, monitor);
consoleService.writeOutput("\n"); //$NON-NLS-1$
} catch (IOException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e));
throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e)); //$NON-NLS-1$
}
// TODO if there are references we want to watch, return them here
@ -71,8 +72,8 @@ public class ArduinoBuilder extends IncrementalProjectBuilder {
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()));
IConsoleService consoleService = Activator.getService(IConsoleService.class);
consoleService.writeOutput(String.format("Cleaning %s\n", project.getName()));
ArduinoBuildConfiguration config = getBuildConfig().getAdapter(ArduinoBuildConfiguration.class);
@ -81,15 +82,16 @@ public class ArduinoBuilder extends IncrementalProjectBuilder {
config.setEnvironment(processBuilder.environment());
Process process = processBuilder.start();
consoleService.monitor(process, config.getBuildConsoleParsers(), config.getBuildFolder());
consoleService.monitor(process, config.getConsoleParsers(), config.getBuildFolder());
config.getBuildFolder().refreshLocal(IResource.DEPTH_INFINITE, monitor);
consoleService.writeOutput("\n"); //$NON-NLS-1$
} catch (IOException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e));
throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e)); //$NON-NLS-1$
}
}
private void showSizes(ArduinoBuildConfiguration config, ArduinoConsoleService console) throws CoreException {
private void showSizes(ArduinoBuildConfiguration config, IConsoleService console) throws CoreException {
try {
int codeSize = -1;
int dataSize = -1;

View file

@ -1,53 +0,0 @@
package org.eclipse.cdt.arduino.core.internal.console;
public abstract class ArduinoConsoleParser {
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
* representing a regular expression.
*
* @return the regular expression to be used for matching
*/
public String getPattern() {
return pattern;
}
/**
* Returns the flags to use when compiling this pattern match listener's
* regular expression, as defined by by
* <code>Pattern.compile(String regex, int flags)</code>
*
* @return the flags to use when compiling this pattern match listener's
* regular expression
* @see java.util.regex.Pattern#compile(java.lang.String, int)
*/
public int getCompilerFlags() {
return flags;
}
/**
* Returns a simple regular expression used to identify lines that may match
* this pattern matcher's complete pattern, or <code>null</code>. Use of
* this attribute can improve performance by disqualifying lines from the
* search. When a line is found containing a match for this expression, the
* line is searched from the beginning for this pattern matcher's complete
* pattern. Lines not containing this pattern are discarded.
*
* @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() {
return lineQualifier;
}
}

View file

@ -1,25 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.arduino.core.internal.console;
import java.io.IOException;
import org.eclipse.core.resources.IFolder;
public interface ArduinoConsoleService {
void monitor(Process process, ArduinoConsoleParser[] consoleParsers, IFolder buildDirectory) throws IOException;
void writeOutput(String msg) throws IOException;
void writeError(String msg) throws IOException;
}

View file

@ -1,67 +0,0 @@
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

@ -16,8 +16,8 @@ import org.eclipse.cdt.arduino.core.internal.Activator;
import org.eclipse.cdt.arduino.core.internal.Messages;
import org.eclipse.cdt.arduino.core.internal.board.ArduinoBoard;
import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration;
import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleService;
import org.eclipse.cdt.arduino.core.internal.remote.ArduinoRemoteConnection;
import org.eclipse.cdt.core.build.IConsoleService;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@ -76,7 +76,7 @@ public class ArduinoLaunchConfigurationDelegate extends LaunchConfigurationDeleg
new Job(Messages.ArduinoLaunchConfigurationDelegate_0) {
protected IStatus run(IProgressMonitor monitor) {
try {
ArduinoConsoleService consoleService = Activator.getConsoleService();
IConsoleService consoleService = Activator.getService(IConsoleService.class);
IRemoteConnection target = getTarget(configuration);
if (target == null) {
return new Status(IStatus.ERROR, Activator.getId(),

View file

@ -30,12 +30,6 @@
project="true">
</wizard>
</extension>
<extension
point="org.eclipse.cdt.arduino.core.consoleService">
<provider
class="org.eclipse.cdt.arduino.ui.internal.launch.ArduinoConsole">
</provider>
</extension>
<extension
point="org.eclipse.ui.propertyPages">
<page

View file

@ -1,162 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
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.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;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;
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);
ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { console });
out = console.newMessageStream();
err = console.newMessageStream();
// set the colors
final Display display = Display.getDefault();
display.syncExec(new Runnable() {
@Override
public void run() {
out.setColor(display.getSystemColor(SWT.COLOR_BLACK));
err.setColor(display.getSystemColor(SWT.COLOR_RED));
}
});
ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.PRE_BUILD);
}
}
@Override
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);
// Output stream reader
new Thread(Messages.ArduinoLaunchConsole_2) {
public void run() {
try (BufferedReader processOut = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
for (String line = processOut.readLine(); line != null; line = processOut.readLine()) {
out.write(line);
out.write('\n');
}
} catch (IOException e) {
e.printStackTrace();
} finally {
sema.release();
}
}
}.start();
// Error stream reader
new Thread(Messages.ArduinoLaunchConsole_2) {
public void run() {
try (BufferedReader processErr = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
for (String line = processErr.readLine(); line != null; line = processErr.readLine()) {
err.write(line);
out.write('\n');
}
} catch (IOException e) {
e.printStackTrace();
} finally {
sema.release();
}
}
}.start();
try {
sema.acquire();
process.waitFor();
} catch (InterruptedException e) {
Activator.log(e);
}
}
@Override
public void writeOutput(String msg) throws IOException {
out.write(msg);
}
@Override
public void writeError(String msg) throws IOException {
err.write(msg);
}
}

View file

@ -1,30 +0,0 @@
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

@ -1,43 +0,0 @@
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();
}
}