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

bug 295625: Error highlighting in Build Console

patch from Dmitry Kozlov
This commit is contained in:
Andrew Gvozdev 2010-02-25 20:53:51 +00:00
parent 5cdc9c1c05
commit 4735712764
26 changed files with 837 additions and 172 deletions

View file

@ -8,6 +8,7 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
* Tianchao Li (tianchao.li@gmail.com) - arbitrary build directory (bug #136136)
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.make.core;
@ -205,11 +206,11 @@ public class MakeBuilder extends ACBuilder {
if (last == null) {
last = new Integer(100);
}
StreamMonitor streamMon = new StreamMonitor(new SubProgressMonitor(monitor, 100), cos, last.intValue());
ErrorParserManager epm = new ErrorParserManager(getProject(), workingDirectoryURI, this, info.getErrorParsers());
epm.setOutputStream(streamMon);
OutputStream stdout = epm.getOutputStream();
OutputStream stderr = epm.getOutputStream();
epm.setOutputStream(cos);
StreamMonitor streamMon = new StreamMonitor(new SubProgressMonitor(monitor, 100), epm, last.intValue());
OutputStream stdout = streamMon;
OutputStream stderr = streamMon;
// Sniff console output for scanner info
ConsoleOutputSniffer sniffer = ScannerInfoConsoleParserFactory.getMakeBuilderOutputSniffer(
stdout, stderr, getProject(), workingDirectory, null, this, null);
@ -256,7 +257,6 @@ public class MakeBuilder extends ACBuilder {
monitor.subTask(MakeMessages.getString("MakeBuilder.Creating_Markers")); //$NON-NLS-1$
consoleOut.close();
consoleErr.close();
epm.reportProblems();
cos.close();
}
} catch (Exception e) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2009 Intel Corporation and others.
* Copyright (c) 2007, 2010 Intel Corporation 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
@ -8,6 +8,7 @@
* Contributors:
* Intel Corporation - Initial API and implementation
* IBM Corporation
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.internal.core;
@ -1035,7 +1036,6 @@ public class CommonBuilder extends ACBuilder {
monitor.subTask(ManagedMakeMessages
.getResourceString(MARKERS));
//TODO: addBuilderMarkers(epm);
epm.reportProblems();
bsMngr.setProjectBuildState(currentProject, pBS);
} else {
@ -1912,11 +1912,11 @@ public class CommonBuilder extends ACBuilder {
if (last == null) {
last = new Integer(100);
}
StreamMonitor streamMon = new StreamMonitor(new SubProgressMonitor(monitor, 100), cos, last.intValue());
ErrorParserManager epm = new ErrorParserManager(currProject, workingDirectoryURI, this, builder.getErrorParsers());
epm.setOutputStream(streamMon);
OutputStream stdout = epm.getOutputStream();
OutputStream stderr = epm.getOutputStream();
epm.setOutputStream(cos);
StreamMonitor streamMon = new StreamMonitor(new SubProgressMonitor(monitor, 100), epm, last.intValue());
OutputStream stdout = streamMon;
OutputStream stderr = streamMon;
// Sniff console output for scanner info
// ICfgScannerConfigBuilderInfo2Set container = CfgScannerConfigProfileManager.getCfgScannerConfigBuildInfo(cfg);
// CfgInfoContext context = new CfgInfoContext(cfg);
@ -1980,7 +1980,6 @@ public class CommonBuilder extends ACBuilder {
monitor.subTask(ManagedMakeMessages.getResourceString("MakeBuilder.Creating_Markers")); //$NON-NLS-1$
consoleOut.close();
consoleErr.close();
epm.reportProblems();
cos.close();
}
} catch (Exception e) {

View file

@ -1146,7 +1146,6 @@ public class GeneratedMakefileBuilder extends ACBuilder {
monitor.subTask(ManagedMakeMessages
.getResourceString(MARKERS));
addBuilderMarkers(epm);
epm.reportProblems();
consoleOutStream.close();
}
}
@ -1334,10 +1333,8 @@ public class GeneratedMakefileBuilder extends ACBuilder {
epmOutputStream.close();
epmOutputStream = null;
// Generate any error markers that the build has discovered
monitor.subTask(ManagedMakeMessages
.getResourceString(MARKERS));
monitor.subTask(ManagedMakeMessages.getResourceString(MARKERS));
addBuilderMarkers(epm);
epm.reportProblems();
} else {
buf = new StringBuffer();
buf.append(ManagedMakeMessages.getFormattedString(NOTHING_BUILT, getProject().getName()));
@ -1568,7 +1565,6 @@ public class GeneratedMakefileBuilder extends ACBuilder {
// Generate any error markers that the build has discovered
addBuilderMarkers(epm);
epm.reportProblems();
consoleOutStream.close();
} catch (Exception e) {
StringBuffer buf = new StringBuffer();

View file

@ -156,7 +156,7 @@ public class ErrorParserEfsFileMatchingTest extends TestCase {
line = line + '\n';
epManager.write(line.getBytes(), 0, line.length());
epManager.close();
epManager.reportProblems();
epManager.getOutputStream().close();
}
/**
@ -175,7 +175,7 @@ public class ErrorParserEfsFileMatchingTest extends TestCase {
line = line + '\n';
epManager.write(line.getBytes(), 0, line.length());
epManager.close();
epManager.reportProblems();
epManager.getOutputStream().close();
}
/**

View file

@ -158,7 +158,7 @@ public class ErrorParserFileMatchingTest extends TestCase {
line = line + '\n';
epManager.write(line.getBytes(), 0, line.length());
epManager.close();
epManager.reportProblems();
epManager.getOutputStream().close();
}
/**

View file

@ -153,7 +153,7 @@ public class ErrorParserManagerTest extends TestCase {
private void end() throws IOException {
epManager.getOutputStream();
epManager.close();
epManager.reportProblems();
epManager.getOutputStream().close();
}
public void testParsersSanity() throws CoreException, IOException {

View file

@ -125,7 +125,7 @@ public abstract class GenericErrorParserTests extends TestCase {
transferInputStreamToOutputStream(inputStream, manager.getOutputStream(), 1024);
manager.close();
manager.reportProblems();
manager.getOutputStream().close();
if (expectedErrorCount >= 0) {
assertEquals(expectedErrorCount, markerGenerator.numErrors);

View file

@ -207,7 +207,6 @@ public class RegexErrorParserTests extends TestCase {
regexErrorParser.processLine("Variable!Description!10!"+fileName, epManager);
errorList.clear();
epManager.reportProblems();
assertEquals(3, errorList.size());
// Regular
@ -704,7 +703,6 @@ public class RegexErrorParserTests extends TestCase {
regexErrorParser.processLine("pattern wrong", epManager);
errorList.clear();
epManager.reportProblems();
assertEquals(0, errorList.size());
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2009 IBM Corporation and others.
* Copyright (c) 2005, 2010 IBM Corporation 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
@ -10,6 +10,7 @@
* Sergey Prigogin (Google)
* James Blackburn (Broadcom) - Bug 247838
* Andrew Gvozdev (Quoin Inc)
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.core;
@ -25,6 +26,7 @@ import java.util.Vector;
import org.eclipse.cdt.core.errorparsers.ErrorParserNamedWrapper;
import org.eclipse.cdt.core.resources.ACBuilder;
import org.eclipse.cdt.internal.core.IErrorMarkeredOutputStream;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
import org.eclipse.cdt.internal.errorparsers.ErrorParserExtensionManager;
import org.eclipse.cdt.utils.CygPath;
@ -307,7 +309,6 @@ public class ErrorParserManager extends OutputStream {
if (fErrorParsers.size() == 0)
return;
String lineTrimmed = line.trim();
lineCounter++;
@ -337,6 +338,9 @@ public class ErrorParserManager extends OutputStream {
// It should not stop parsing of the rest of output.
try {
if (curr.processLine(lineToParse, this)) {
ProblemMarkerInfo m = fErrors.size() > 0 ? fErrors.get(0): null;
outputLine(line, m);
fErrors.clear();
return;
}
} catch (Exception e){
@ -345,8 +349,29 @@ public class ErrorParserManager extends OutputStream {
}
}
}
outputLine(line, null);
}
/**
* Conditionally output line to outputStream. If stream
* supports error markers, use it, otherwise use conventional stream
*/
private void outputLine(String line, ProblemMarkerInfo marker) {
String l = line + "\n"; //$NON-NLS-1$
if ( outputStream == null ) return;
try {
if ( marker != null && outputStream instanceof IErrorMarkeredOutputStream ) {
IErrorMarkeredOutputStream s = (IErrorMarkeredOutputStream) outputStream;
s.write(l, marker);
} else {
byte[] b = l.getBytes();
outputStream.write(b, 0, b.length);
}
} catch (IOException e) {
CCorePlugin.log(e);
}
}
/**
* @return counter counting processed lines of output
* @since 5.2
@ -500,7 +525,6 @@ public class ErrorParserManager extends OutputStream {
/**
* Add marker to the list of error markers.
* Markers are actually added in the end of processing in {@link #reportProblems()}.
*
* @param file - resource to add the new marker.
* @param lineNumber - line number of the error.
@ -514,7 +538,6 @@ public class ErrorParserManager extends OutputStream {
/**
* Add marker to the list of error markers.
* Markers are actually added in the end of processing in {@link #reportProblems()}.
*
* @param file - resource to add the new marker.
* @param lineNumber - line number of the error.
@ -530,6 +553,7 @@ public class ErrorParserManager extends OutputStream {
public void generateExternalMarker(IResource file, int lineNumber, String desc, int severity, String varName, IPath externalPath) {
ProblemMarkerInfo problemMarkerInfo = new ProblemMarkerInfo(file, lineNumber, desc, severity, varName, externalPath);
fErrors.add(problemMarkerInfo);
fMarkerGenerator.addMarker(problemMarkerInfo);
if (severity == IMarkerGenerator.SEVERITY_ERROR_RESOURCE)
hasErrors = true;
}
@ -544,6 +568,8 @@ public class ErrorParserManager extends OutputStream {
/**
* Method setOutputStream.
* Note: you have to close this stream explicitly
* don't rely on ErrorParserManager.close().
* @param os - output stream
*/
public void setOutputStream(OutputStream os) {
@ -551,8 +577,9 @@ public class ErrorParserManager extends OutputStream {
}
/**
* Method getOutputStream. It has a reference count
* the stream must be close the same number of time this method was call.
* Method getOutputStream.
* Note: you have to close this stream explicitly
* don't rely on ErrorParserManager.close().
* @return OutputStream
*/
public OutputStream getOutputStream() {
@ -562,14 +589,14 @@ public class ErrorParserManager extends OutputStream {
/**
* @see java.io.OutputStream#close()
* Note: don't rely on this method to close underlying OutputStream,
* close it explicitly
*/
@Override
public void close() throws IOException {
public synchronized void close() throws IOException {
if (nOpens > 0 && --nOpens == 0) {
checkLine(true);
fDirectoryStack.removeAllElements();
if (outputStream != null)
outputStream.close();
}
}
@ -589,8 +616,6 @@ public class ErrorParserManager extends OutputStream {
public synchronized void write(int b) throws IOException {
currentLine.append((char) b);
checkLine(false);
if (outputStream != null)
outputStream.write(b);
}
@Override
@ -604,10 +629,12 @@ public class ErrorParserManager extends OutputStream {
}
currentLine.append(new String(b, 0, len));
checkLine(false);
if (outputStream != null)
outputStream.write(b, off, len);
}
// This method examines contents of currentLine buffer
// if it contains whole line this line is checked by error
// parsers (processLine method).
// If flush is true rest of line is checked by error parsers.
private void checkLine(boolean flush) {
String buffer = currentLine.toString();
int i = 0;
@ -632,7 +659,8 @@ public class ErrorParserManager extends OutputStream {
}
/**
* Create actual markers from the list of collected problems.
* @deprecated as of 5.2. This method is no longer reporting problems.
* The problem markers are generated after processing each line.
*
* @return {@code true} if detected a problem indicating that build failed.
* The semantics of the return code is inconsistent. As far as build is concerned
@ -640,18 +668,9 @@ public class ErrorParserManager extends OutputStream {
* {@link IMarkerGenerator#SEVERITY_ERROR_RESOURCE} and
* {@link IMarkerGenerator#SEVERITY_ERROR_BUILD}
*/
@Deprecated
public boolean reportProblems() {
boolean reset = false;
if (nOpens == 0) {
for (ProblemMarkerInfo problemMarkerInfo : fErrors) {
if (problemMarkerInfo.severity == IMarkerGenerator.SEVERITY_ERROR_BUILD) {
reset = true;
}
fMarkerGenerator.addMarker(problemMarkerInfo);
}
fErrors.clear();
}
return reset;
return false;
}
/**

View file

@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2010 CodeSourcery 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:
* Dmitry Kozlov (CodeSourcery) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core;
import java.io.IOException;
import org.eclipse.cdt.core.ProblemMarkerInfo;
/**
* Output stream for use in build console capable of processing markers info
* attached to the output.
* @since 5.2
*/
public interface IErrorMarkeredOutputStream {
public void write(String s, ProblemMarkerInfo marker) throws IOException;
public void write(byte[] b, int offset, int len) throws IOException;
public void flush() throws IOException;
public void close() throws IOException;
}

View file

@ -29,6 +29,8 @@ ConsolePreferencePage.outputColor.label=Output text color
ConsolePreferencePage.infoColor.label=Information message text color
ConsolePreferencePage.errorColor.label=Error message text color
ConsolePreferencePage.backgroundColor.label=Background color
ConsolePreferencePage.problemBackgroundColor.label=Background color for build problems
ConsolePreferencePage.problemHighlightedColor.label=Highlighting color for build problems
# ------- Project/Prefernces/Wizards COnfiguration blocks -------

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2002, 2007 QNX Software Systems and others.
* Copyright (c) 2002, 2010 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
@ -8,6 +8,7 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
* Red Hat Inc. - Multiple build console support
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
@ -22,16 +23,24 @@ import org.eclipse.ui.console.IConsoleView;
import org.eclipse.ui.part.IPageBookViewPage;
public class BuildConsole extends AbstractConsole {
/**
* Menu group identifier for the console view context menu and toolbar, for actions pertaining to
* error navigation (value <code>"errorGroup"</code>).
*/
public static final String ERROR_GROUP = "errorGroup"; //$NON-NLS-1$
/**
* Property constant indicating the color of a stream has changed.
*/
public static final String P_STREAM_COLOR = CUIPlugin.PLUGIN_ID + ".CONSOLE_P_STREAM_COLOR"; //$NON-NLS-1$
private static BuildConsolePage fBuildConsolePage;
private IBuildConsoleManager fConsoleManager;
private String fConsoleName;
private String fConsoleId;
private Color fBackground;
private Color fBackground;
public BuildConsole(IBuildConsoleManager manager, String name, String id) {
super(name, CPluginImages.DESC_BUILD_CONSOLE);
@ -41,7 +50,12 @@ public class BuildConsole extends AbstractConsole {
}
public IPageBookViewPage createPage(IConsoleView view) {
return new BuildConsolePage(view, this, fConsoleId);
fBuildConsolePage = new BuildConsolePage(view, this, fConsoleId);
return fBuildConsolePage;
}
static BuildConsolePage getPage() {
return fBuildConsolePage;
}
public void setTitle(IProject project) {
@ -53,7 +67,7 @@ public class BuildConsole extends AbstractConsole {
}
public IBuildConsoleManager getConsoleManager() {
return fConsoleManager;
return fConsoleManager;
}
public void setBackground(Color background) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2002, 2007 QNX Software Systems and others.
* Copyright (c) 2002, 2010 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
@ -8,6 +8,7 @@
* Contributors:
* QNX Software Systems - initial API and implementation
* Red Hat Inc. - multiple build console support
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
@ -53,8 +54,16 @@ public class BuildConsoleManager implements IBuildConsoleManager, IResourceChang
ListenerList listeners = new ListenerList();
BuildConsole fConsole;
private Map<IProject, BuildConsolePartitioner> fConsoleMap = new HashMap<IProject, BuildConsolePartitioner>();
Color infoColor, outputColor, errorColor, backgroundColor;
BuildConsoleStream infoStream, outputStream, errorStream;
Color infoColor, outputColor, errorColor, backgroundColor, problemHighlightedColor, problemBackgroundColor;
public Color getProblemHighlightedColor() {
return problemHighlightedColor;
}
public Color getProblemBackgroundColor() {
return problemBackgroundColor;
}
BuildConsoleStreamDecorator infoStream, outputStream, errorStream;
String fName, fContextMenuId;
static public final int BUILD_STREAM_TYPE_INFO = 0;
@ -159,6 +168,8 @@ public class BuildConsoleManager implements IBuildConsoleManager, IResourceChang
outputColor.dispose();
errorColor.dispose();
backgroundColor.dispose();
problemBackgroundColor.dispose();
problemHighlightedColor.dispose();
}
ConsolePlugin.getDefault().getConsoleManager().removeConsoles(new org.eclipse.ui.console.IConsole[]{fConsole});
CUIPlugin.getWorkspace().removeResourceChangeListener(this);
@ -177,9 +188,9 @@ public class BuildConsoleManager implements IBuildConsoleManager, IResourceChang
}
public void startup(String name, String id) {
infoStream = new BuildConsoleStream();
outputStream = new BuildConsoleStream();
errorStream = new BuildConsoleStream();
infoStream = new BuildConsoleStreamDecorator();
outputStream = new BuildConsoleStreamDecorator();
errorStream = new BuildConsoleStreamDecorator();
fName = name;
fContextMenuId = id;
@ -205,6 +216,8 @@ public class BuildConsoleManager implements IBuildConsoleManager, IResourceChang
errorStream.setColor(errorColor);
backgroundColor = createColor(CUIPlugin.getStandardDisplay(), BuildConsolePreferencePage.PREF_BUILDCONSOLE_BACKGROUND_COLOR);
fConsole.setBackground(backgroundColor);
problemHighlightedColor = createColor(CUIPlugin.getStandardDisplay(), BuildConsolePreferencePage.PREF_BUILDCONSOLE_PROBLEM_HIGHLIGHTED_COLOR);
problemBackgroundColor = createColor(CUIPlugin.getStandardDisplay(), BuildConsolePreferencePage.PREF_BUILDCONSOLE_PROBLEM_BACKGROUND_COLOR);
}
});
CUIPlugin.getWorkspace().addResourceChangeListener(this);
@ -239,10 +252,33 @@ public class BuildConsoleManager implements IBuildConsoleManager, IResourceChang
fConsole.setBackground(newColor);
backgroundColor.dispose();
backgroundColor = newColor;
} else if (property.equals(BuildConsolePreferencePage.PREF_BUILDCONSOLE_PROBLEM_HIGHLIGHTED_COLOR)) {
Color newColor = createColor(CUIPlugin.getStandardDisplay(), BuildConsolePreferencePage.PREF_BUILDCONSOLE_PROBLEM_HIGHLIGHTED_COLOR);
problemHighlightedColor.dispose();
problemHighlightedColor = newColor;
redrawTextViewer();
} else if (property.equals(BuildConsolePreferencePage.PREF_BUILDCONSOLE_PROBLEM_BACKGROUND_COLOR)) {
Color newColor = createColor(CUIPlugin.getStandardDisplay(), BuildConsolePreferencePage.PREF_BUILDCONSOLE_PROBLEM_BACKGROUND_COLOR);
problemBackgroundColor.dispose();
problemBackgroundColor = newColor;
redrawTextViewer();
}
}
public BuildConsoleStream getStream(int type) throws CoreException {
private void redrawTextViewer() {
final BuildConsolePage p = BuildConsole.getPage();
if ( p == null ) return;
final BuildConsoleViewer v = p.getViewer();
if ( v == null ) return;
Display display = Display.getDefault();
display.asyncExec(new Runnable() {
public void run() {
v.getTextWidget().redraw();
}
});
}
public BuildConsoleStreamDecorator getStreamDecorator(int type) throws CoreException {
switch (type) {
case BUILD_STREAM_TYPE_ERROR :
return errorStream;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2002, 2008 QNX Software Systems and others.
* Copyright (c) 2002, 2010 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
@ -8,6 +8,7 @@
* Contributors:
* QNX Software Systems - initial API and implementation
* Red Hat Inc. - multiple build console support
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
@ -19,9 +20,12 @@ import java.util.Map;
import java.util.ResourceBundle;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
@ -36,6 +40,7 @@ import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
@ -59,6 +64,8 @@ import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.console.IConsoleConstants;
@ -66,15 +73,21 @@ import org.eclipse.ui.console.IConsoleView;
import org.eclipse.ui.console.actions.ClearOutputAction;
import org.eclipse.ui.console.actions.TextViewerAction;
import org.eclipse.ui.console.actions.TextViewerGotoLineAction;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.ide.ResourceUtil;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.Page;
import org.eclipse.ui.texteditor.FindReplaceAction;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.texteditor.IUpdate;
import org.eclipse.cdt.core.ProblemMarkerInfo;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.IBuildConsoleEvent;
import org.eclipse.cdt.ui.IBuildConsoleListener;
import org.eclipse.cdt.ui.IBuildConsoleManager;
import org.eclipse.cdt.internal.ui.preferences.BuildConsolePreferencePage;
@ -86,6 +99,10 @@ public class BuildConsolePage extends Page
ITextListener,
IAdaptable {
static final int POSITION_NEXT = -1;
static final int POSITION_PREV = -2;
static final int POSITION_FIST = -3;
private BuildConsole fConsole;
private IConsoleView fConsoleView;
private String fContextMenuId;
@ -109,6 +126,9 @@ public class BuildConsolePage extends Page
private Menu fMenu;
private ScrollLockAction fScrollLockAction;
private boolean fIsLocked;
private NextErrorAction fNextErrorAction;
private PreviousErrorAction fPreviousErrorAction;
private ShowErrorAction fShowErrorAction;
/**
* @param view
@ -137,7 +157,13 @@ public class BuildConsolePage extends Page
protected IDocument setDocument() {
IProject project = getProject();
if (project != null) {
getViewer().setDocument(getConsole().getConsoleManager().getConsoleDocument(project));
IBuildConsoleManager consoleManager = getConsole().getConsoleManager();
getViewer().setDocument(consoleManager.getConsoleDocument(project));
IConsole console = consoleManager.getConsole(project);
if ( console instanceof BuildConsolePartitioner) {
BuildConsolePartitioner par = (BuildConsolePartitioner)console;
showError(par, fShowErrorAction.isChecked() );
}
}
return null;
}
@ -206,6 +232,7 @@ public class BuildConsolePage extends Page
setTabs(CUIPlugin.getDefault().getPluginPreferences().getInt(BuildConsolePreferencePage.PREF_BUILDCONSOLE_TAB_WIDTH));
getConsole().addPropertyChangeListener(this);
CUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
fViewer.addTextListener(this);
fViewer.getTextWidget().setBackground(getConsole().getBackground());
@ -238,8 +265,8 @@ public class BuildConsolePage extends Page
final Object source = event.getSource();
final String property = event.getProperty();
if (BuildConsole.P_STREAM_COLOR.equals(property) && source instanceof BuildConsoleStream) {
BuildConsoleStream stream = (BuildConsoleStream)source;
if (BuildConsole.P_STREAM_COLOR.equals(property) && source instanceof BuildConsoleStreamDecorator) {
BuildConsoleStreamDecorator stream = (BuildConsoleStreamDecorator)source;
if (stream.getConsole().equals(getConsole()) && getControl() != null) {
Display display = getControl().getDisplay();
display.asyncExec(new Runnable() {
@ -261,6 +288,10 @@ public class BuildConsolePage extends Page
protected void createActions() {
fClearOutputAction = new ClearOutputAction(getViewer());
fScrollLockAction = new ScrollLockAction(getViewer());
fNextErrorAction = new NextErrorAction(this);
fPreviousErrorAction = new PreviousErrorAction(this);
fShowErrorAction = new ShowErrorAction();
fScrollLockAction.setChecked(fIsLocked);
getViewer().setAutoScroll(!fIsLocked);
// In order for the clipboard actions to accessible via their shortcuts
@ -311,6 +342,11 @@ public class BuildConsolePage extends Page
}
protected void configureToolBar(IToolBarManager mgr) {
mgr.insertBefore(IConsoleConstants.OUTPUT_GROUP, new GroupMarker(BuildConsole.ERROR_GROUP));
mgr.appendToGroup(BuildConsole.ERROR_GROUP, fPreviousErrorAction);
mgr.appendToGroup(BuildConsole.ERROR_GROUP, fNextErrorAction);
mgr.appendToGroup(BuildConsole.ERROR_GROUP, fShowErrorAction);
mgr.appendToGroup(IConsoleConstants.OUTPUT_GROUP, fScrollLockAction);
mgr.appendToGroup(IConsoleConstants.OUTPUT_GROUP, fClearOutputAction);
}
@ -506,4 +542,88 @@ public class BuildConsolePage extends Page
findReplace.update();
}
}
/**
* Highlight next/previous error or error by console offset
* @param position POSITION_NEXT (-1), POSITION_PREV (-2), or offset
*/
void moveToError(int position) {
IProject project = getProject();
IBuildConsoleManager consoleManager = CUIPlugin.getDefault().getConsoleManager();
IConsole console = consoleManager.getConsole(project);
if ( console instanceof BuildConsolePartitioner) {
BuildConsolePartitioner par = (BuildConsolePartitioner)console;
// Move to specified line in the model (BuildConsolePartitioner)
if ( position == POSITION_NEXT ) {
par.fDocumentMarkerManager.moveToNextError();
} else if ( position == POSITION_PREV ) {
par.fDocumentMarkerManager.moveToPreviousError();
} else if ( position == POSITION_FIST ) {
par.fDocumentMarkerManager.moveToFirstError();
} else if ( position >= 0 ) {
if ( ! par.fDocumentMarkerManager.moveToErrorByOffset(position) ) {
// we haven't moved, because offset points to non-error partition
return;
}
}
showError(par, position > 0 || fShowErrorAction.isChecked() );
}
}
/**
* Highlight current error and show it in editor
*/
public void showError(BuildConsolePartitioner par, boolean openInEditor) {
// Highlight current error
BuildConsolePartition p = par.fDocumentMarkerManager.getCurrentPartition();
if ( p == null ) return;
getViewer().selectPartition(par, p);
// Show error in editor if necessary
// (always show when absolute positioning, otherwise depends
// on fShowErrorAction state)
if ( openInEditor ) {
openErrorInEditor(par.fDocumentMarkerManager.getCurrentErrorMarker());
}
}
/**
* Open error specified by marker in editor
*/
public static void openErrorInEditor(ProblemMarkerInfo marker) {
IWorkbenchWindow window = CUIPlugin.getActiveWorkbenchWindow();
if ( marker == null || marker.file == null || window == null ) return;
IWorkbenchPage page = window.getActivePage();
if (page == null) return;
IEditorPart editor = page.getActiveEditor();
if (editor != null) {
IEditorInput input = editor.getEditorInput();
IFile file = ResourceUtil.getFile(input);
if (file != null && file.equals(marker.file) && OpenStrategy.activateOnOpen()) {
page.activate(editor);
}
}
if ( marker.file instanceof IFile ) {
try {
// Find IMarker corresponding to ProblemMarkerInfo
IMarker mrkrs[] = marker.file.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_ONE);
for (IMarker m: mrkrs) {
if ( marker.lineNumber == ((Integer)m.getAttribute(IMarker.LINE_NUMBER)).intValue() &&
marker.description.equals(m.getAttribute(IMarker.MESSAGE)) &&
marker.severity == ((Integer)m.getAttribute(IMarker.SEVERITY)).intValue() ) {
IDE.openEditor(page, m, OpenStrategy.activateOnOpen());
return;
}
}
} catch (PartInitException e) {
CUIPlugin.log(e);
} catch (CoreException e) {
CUIPlugin.log(e);
}
}
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2002, 2006 QNX Software Systems and others.
* Copyright (c) 2002, 2010 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
@ -7,29 +7,39 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
import org.eclipse.cdt.core.ProblemMarkerInfo;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.jface.text.TypedRegion;
public class BuildConsolePartition extends TypedRegion {
/**
* Associated stream
*/
private BuildConsoleStream fStream;
/** Associated stream */
private BuildConsoleStreamDecorator fStream;
/** Marker associated with this partition if any */
private ProblemMarkerInfo fMarker;
/**
* Partition type
*/
/** Partition type */
public static final String CONSOLE_PARTITION_TYPE = CUIPlugin.getPluginId() + ".CONSOLE_PARTITION_TYPE"; //$NON-NLS-1$
public BuildConsolePartition(BuildConsoleStream stream, int offset, int length) {
super(offset, length, CONSOLE_PARTITION_TYPE);
/** Partition type to report errors in console */
public static final String ERROR_PARTITION_TYPE = CUIPlugin.getPluginId() + ".ERROR_PARTITION_TYPE"; //$NON-NLS-1$
public BuildConsolePartition(BuildConsoleStreamDecorator stream, int offset, int length, String type) {
super(offset, length, type);
fStream = stream;
}
public BuildConsolePartition(BuildConsoleStreamDecorator stream, int offset, int length, String type, ProblemMarkerInfo marker) {
super(offset, length, type);
fStream = stream;
fMarker = marker;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@ -54,7 +64,7 @@ public class BuildConsolePartition extends TypedRegion {
*
* @return this partition's stream
*/
public BuildConsoleStream getStream() {
public BuildConsoleStreamDecorator getStream() {
return fStream;
}
@ -66,6 +76,9 @@ public class BuildConsolePartition extends TypedRegion {
* @return boolean
*/
public boolean canBeCombinedWith(BuildConsolePartition partition) {
// Error partitions never can be combined together
if ( getType() == ERROR_PARTITION_TYPE ) return false;
int start = getOffset();
int end = start + getLength();
int otherStart = partition.getOffset();
@ -88,18 +101,20 @@ public class BuildConsolePartition extends TypedRegion {
int otherEnd = otherStart + partition.getLength();
int theStart = Math.min(start, otherStart);
int theEnd = Math.max(end, otherEnd);
return createNewPartition(theStart, theEnd - theStart);
return createNewPartition(theStart, theEnd - theStart, CONSOLE_PARTITION_TYPE);
}
/**
* Creates a new patition of this type with the given color, offset, and
* length.
*
* Creates a new partition of this type with the given offset, and length.
* @param offset
* @param length
* @return a new partition with the given range
*/
public BuildConsolePartition createNewPartition(int offset, int length) {
return new BuildConsolePartition(getStream(), offset, length);
public BuildConsolePartition createNewPartition(int offset, int length, String type) {
return new BuildConsolePartition(getStream(), offset, length, type, getMarker());
}
public ProblemMarkerInfo getMarker() {
return fMarker;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2002, 2006 QNX Software Systems and others.
* Copyright (c) 2002, 2010 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
@ -7,10 +7,10 @@
*
* Contributors:
* QNX Software Systems - initial API and implementation
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -32,6 +32,7 @@ import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.cdt.core.ConsoleOutputStream;
import org.eclipse.cdt.core.ProblemMarkerInfo;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.ui.CUIPlugin;
@ -54,11 +55,13 @@ public class BuildConsolePartitioner
/**
* The stream that was last appended to
*/
BuildConsoleStream fLastStream = null;
BuildConsoleStreamDecorator fLastStream = null;
BuildConsoleDocument fDocument;
DocumentMarkerManager fDocumentMarkerManager;
boolean killed;
BuildConsoleManager fManager;
Boolean outputStreamClosed = new Boolean(false);
/**
* A queue of stream entries written to standard out and standard err.
@ -72,24 +75,23 @@ public class BuildConsolePartitioner
class StreamEntry {
/**
* Identifier of the stream written to.
*/
private BuildConsoleStream fStream;
/**
* The text written
*/
private StringBuffer fText = null;
/** Identifier of the stream written to. */
private BuildConsoleStreamDecorator fStream;
/** The text written */
private StringBuffer fText = null;
/** Problem marker corresponding to the line of text */
private ProblemMarkerInfo fMarker;
StreamEntry(String text, BuildConsoleStream stream) {
StreamEntry(String text, BuildConsoleStreamDecorator stream, ProblemMarkerInfo marker) {
fText = new StringBuffer(text);
fStream = stream;
fMarker = marker;
}
/**
* Returns the stream identifier
*/
public BuildConsoleStream getStream() {
public BuildConsoleStreamDecorator getStream() {
return fStream;
}
@ -107,6 +109,14 @@ public class BuildConsolePartitioner
public String getText() {
return fText.toString();
}
/**
* Returns error marker
*/
public ProblemMarkerInfo getMarker() {
return fMarker;
}
}
public BuildConsolePartitioner(BuildConsoleManager manager) {
@ -114,6 +124,7 @@ public class BuildConsolePartitioner
fMaxLines = BuildConsolePreferencePage.buildConsoleLines();
fDocument = new BuildConsoleDocument();
fDocument.setDocumentPartitioner(this);
fDocumentMarkerManager = new DocumentMarkerManager(fDocument, this);
connect(fDocument);
}
@ -125,8 +136,7 @@ public class BuildConsolePartitioner
* @param stream
* the stream to append to
*/
public void appendToDocument(String text, BuildConsoleStream stream) {
public void appendToDocument(String text, BuildConsoleStreamDecorator stream, ProblemMarkerInfo marker) {
boolean addToQueue = true;
synchronized (fQueue) {
int i = fQueue.size();
@ -134,13 +144,13 @@ public class BuildConsolePartitioner
StreamEntry entry = fQueue.get(i - 1);
// if last stream is the same and we have not exceeded our
// display write limit, append.
if (entry.getStream() == stream && entry.size() < 10000) {
if (entry.getStream() == stream && entry.size() < 10000 && entry.getMarker() == marker) {
entry.appendText(text);
addToQueue = false;
}
}
if (addToQueue) {
fQueue.add(new StreamEntry(text, stream));
fQueue.add(new StreamEntry(text, stream, marker));
}
}
Runnable r = new Runnable() {
@ -155,12 +165,15 @@ public class BuildConsolePartitioner
fLastStream = entry.getStream();
try {
warnOfContentChange(fLastStream);
if (fLastStream == null) {
fDocument.set(entry.getText());
} else {
fDocument.replace(fDocument.getLength(), 0, entry.getText());
checkOverflow();
if ( fLastStream == null ) {
// special case to empty document
fPartitions.clear();
fDocumentMarkerManager.clear();
fDocument.set(""); //$NON-NLS-1$
}
addStreamEntryToDocument(entry);
checkOverflow();
} catch (BadLocationException e) {
}
}
@ -171,7 +184,25 @@ public class BuildConsolePartitioner
}
}
void warnOfContentChange(BuildConsoleStream stream) {
private void addStreamEntryToDocument(StreamEntry entry) throws BadLocationException {
if ( entry.getMarker() == null ) {
// It is plain unmarkered console output
addPartition(new BuildConsolePartition(fLastStream,
fDocument.getLength(),
entry.getText().length(),
BuildConsolePartition.CONSOLE_PARTITION_TYPE));
} else {
// this text line in entry is markered with ProblemMarkerInfo,
// create special partition for it.
addPartition(new BuildConsolePartition(fLastStream,
fDocument.getLength(),
entry.getText().length(),
BuildConsolePartition.ERROR_PARTITION_TYPE, entry.getMarker()));
}
fDocument.replace(fDocument.getLength(), 0, entry.getText());
}
void warnOfContentChange(BuildConsoleStreamDecorator stream) {
if (stream != null) {
ConsolePlugin.getDefault().getConsoleManager().warnOfContentChange(stream.getConsole());
}
@ -237,7 +268,8 @@ public class BuildConsolePartitioner
ITypedRegion partition = fPartitions.get(i);
int partitionStart = partition.getOffset();
int partitionEnd = partitionStart + partition.getLength();
if ( (offset >= partitionStart && offset <= partitionEnd) || (offset < partitionStart && end >= partitionStart)) {
if ( (offset >= partitionStart && offset <= partitionEnd) ||
(offset < partitionStart && end >= partitionStart)) {
list.add(partition);
}
}
@ -266,7 +298,6 @@ public class BuildConsolePartitioner
fPartitions.clear();
return new Region(0, 0);
}
addPartition(new BuildConsolePartition(fLastStream, event.getOffset(), text.length()));
ITypedRegion[] affectedRegions = computePartitioning(event.getOffset(), text.length());
if (affectedRegions.length == 0) {
return null;
@ -308,17 +339,19 @@ public class BuildConsolePartitioner
int offset = region.getOffset();
if (offset < overflow) {
int endOffset = offset + region.getLength();
if (endOffset < overflow) {
// remove partition
if (endOffset < overflow ||
messageConsolePartition.getType() == BuildConsolePartition.ERROR_PARTITION_TYPE ) {
// remove partition,
// partitions with problem markers can't be split - remove them too
} else {
// split partition
int length = endOffset - overflow;
newPartition = messageConsolePartition.createNewPartition(0, length);
newPartition = messageConsolePartition.createNewPartition(0, length, messageConsolePartition.getType());
}
} else {
// modify parition offset
// modify partition offset
newPartition = messageConsolePartition.createNewPartition(messageConsolePartition.getOffset()
- overflow, messageConsolePartition.getLength());
- overflow, messageConsolePartition.getLength(), messageConsolePartition.getType());
}
if (newPartition != null) {
newParitions.add(newPartition);
@ -326,6 +359,7 @@ public class BuildConsolePartitioner
}
}
fPartitions = newParitions;
fDocumentMarkerManager.moveToFirstError();
try {
fDocument.replace(0, overflow, ""); //$NON-NLS-1$
@ -336,8 +370,7 @@ public class BuildConsolePartitioner
}
/**
* Adds a new colored input partition, combining with the previous partition
* if possible.
* Adds a new partition, combining with the previous partition if possible.
*/
private BuildConsolePartition addPartition(BuildConsolePartition partition) {
if (fPartitions.isEmpty()) {
@ -371,7 +404,6 @@ public class BuildConsolePartitioner
Display display = CUIPlugin.getStandardDisplay();
if (display != null) {
display.asyncExec(new Runnable() {
public void run() {
fManager.startConsoleActivity(project);
}
@ -379,43 +411,48 @@ public class BuildConsolePartitioner
}
if (BuildConsolePreferencePage.isClearBuildConsole()) {
appendToDocument("", null); //$NON-NLS-1$
}
}
public class BuildOutputStream extends ConsoleOutputStream {
final BuildConsoleStream fStream;
public BuildOutputStream(BuildConsoleStream stream) {
fStream = stream;
}
@Override
public void flush() throws IOException {
}
@Override
public void close() throws IOException {
flush();
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
appendToDocument(new String(b, off, len), fStream);
appendToDocument("", null, null); //$NON-NLS-1$
}
}
public ConsoleOutputStream getOutputStream() throws CoreException {
return new BuildOutputStream(fManager.getStream(BuildConsoleManager.BUILD_STREAM_TYPE_OUTPUT));
outputStreamClosed = Boolean.FALSE;
return new BuildOutputStream(this, fManager.getStreamDecorator(BuildConsoleManager.BUILD_STREAM_TYPE_OUTPUT));
}
public ConsoleOutputStream getInfoStream() throws CoreException {
return new BuildOutputStream(fManager.getStream(BuildConsoleManager.BUILD_STREAM_TYPE_INFO));
return new BuildOutputStream(this, fManager.getStreamDecorator(BuildConsoleManager.BUILD_STREAM_TYPE_INFO));
}
public ConsoleOutputStream getErrorStream() throws CoreException {
return new BuildOutputStream(fManager.getStream(BuildConsoleManager.BUILD_STREAM_TYPE_ERROR));
return new BuildOutputStream(this, fManager.getStreamDecorator(BuildConsoleManager.BUILD_STREAM_TYPE_ERROR));
}
/** This method is useful for future debugging and bugfixing */
@SuppressWarnings("unused")
private void printDocumentPartitioning() {
System.out.println("Document partitioning: "); //$NON-NLS-1$
for (ITypedRegion tr : fPartitions) {
BuildConsolePartition p = (BuildConsolePartition) tr;
int start = p.getOffset();
int end = p.getOffset() + p.getLength();
String text;
String isError = "U"; //$NON-NLS-1$
if (p.getType() == BuildConsolePartition.ERROR_PARTITION_TYPE) {
isError = "E"; //$NON-NLS-1$
} else if (p.getType() == BuildConsolePartition.CONSOLE_PARTITION_TYPE) {
isError = "C"; //$NON-NLS-1$
}
try {
text = fDocument.get(p.getOffset(), p.getLength());
} catch (BadLocationException e) {
text = "N/A"; //$NON-NLS-1$
}
if (text.endsWith("\n")) { //$NON-NLS-1$
text = text.substring(0, text.length() - 1);
}
System.out.println(" " + isError + " " + start + "-" + end + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
":[" + text + "]"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2002, 2006 QNX Software Systems and others.
* Copyright (c) 2009, 2010 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
@ -7,13 +7,14 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
import org.eclipse.swt.graphics.Color;
public class BuildConsoleStream {
public class BuildConsoleStreamDecorator {
private BuildConsole fConsole = null;
private Color fColor = null;
@ -22,7 +23,7 @@ public class BuildConsoleStream {
* Constructs a new stream connected to the given console.
*
*/
public BuildConsoleStream() {
public BuildConsoleStreamDecorator() {
}
public void setConsole(BuildConsole console) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2002, 2006 QNX Software Systems and others.
* Copyright (c) 2002, 2010 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
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
@ -17,14 +18,26 @@ import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.LineBackgroundEvent;
import org.eclipse.swt.custom.LineBackgroundListener;
import org.eclipse.swt.custom.LineStyleEvent;
import org.eclipse.swt.custom.LineStyleListener;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
public class BuildConsoleViewer extends TextViewer implements LineStyleListener {
import org.eclipse.cdt.ui.CUIPlugin;
public class BuildConsoleViewer extends TextViewer
implements LineStyleListener,
LineBackgroundListener,
MouseTrackListener,
MouseListener {
protected InternalDocumentListener fInternalDocumentListener = new InternalDocumentListener();
/**
@ -81,13 +94,15 @@ public class BuildConsoleViewer extends TextViewer implements LineStyleListener
*/
public BuildConsoleViewer(Composite parent) {
super(parent, getSWTStyles());
getTextWidget().setDoubleClickEnabled(true);
getTextWidget().setFont(parent.getFont());
getTextWidget().addLineStyleListener(this);
getTextWidget().setEditable(false);
getTextWidget().setWordWrap(true);
StyledText styledText = getTextWidget();
styledText.addLineStyleListener(this);
styledText.addLineBackgroundListener(this);
styledText.addMouseTrackListener(this);
styledText.setFont(parent.getFont());
styledText.setDoubleClickEnabled(true);
styledText.setEditable(false);
styledText.setWordWrap(true);
}
/**
* Returns the SWT style flags used when instantiating this viewer
@ -121,7 +136,6 @@ public class BuildConsoleViewer extends TextViewer implements LineStyleListener
}
}
/*
* (non-Javadoc)
*
@ -154,21 +168,96 @@ public class BuildConsoleViewer extends TextViewer implements LineStyleListener
*
* @see org.eclipse.swt.custom.LineStyleListener#lineGetStyle(org.eclipse.swt.custom.LineStyleEvent)
*/
public void lineGetStyle(LineStyleEvent event) {
public void lineGetStyle(LineStyleEvent event) {
IDocument document = getDocument();
if (document != null) {
BuildConsolePartitioner partitioner = (BuildConsolePartitioner) document.getDocumentPartitioner();
if (partitioner != null) {
ITypedRegion[] regions = partitioner.computePartitioning(event.lineOffset, event.lineOffset
+ event.lineText.length());
StyleRange[] styles = new StyleRange[regions.length];
for (int i = 0; i < regions.length; i++) {
BuildConsolePartition partition = (BuildConsolePartition) regions[i];
Color color = partition.getStream().getColor();
styles[i] = new StyleRange(partition.getOffset(), partition.getLength(), color, null);
}
event.styles = styles;
if (document == null) return;
BuildConsolePartitioner partitioner = (BuildConsolePartitioner) document.getDocumentPartitioner();
if (partitioner == null) return;
BuildConsolePartition p = partitioner.fDocumentMarkerManager.getCurrentPartition();
Color problemHighlightedColor = partitioner.fManager.getProblemHighlightedColor();
// Note, computePartitioning actually doesn't change anything in partitioning,
// but only computes number of affected regions.
ITypedRegion[] regions = partitioner.computePartitioning(event.lineOffset, event.lineText.length());
StyleRange[] styles = new StyleRange[regions.length];
for (int i = 0; i < regions.length; i++) {
BuildConsolePartition partition = (BuildConsolePartition) regions[i];
Color colorFG = partition.getStream().getColor();
Color colorBG = null;
// Highlight current partition
if ( partition == p ) {
colorFG = problemHighlightedColor;
}
StyleRange styleRange = new StyleRange(partition.getOffset(), partition.getLength(), colorFG, colorBG);
styles[i] = styleRange;
}
event.styles = styles;
}
public void selectPartition(BuildConsolePartitioner partitioner, BuildConsolePartition p) {
try {
int start = partitioner.getDocument().getLineOfOffset(p.getOffset());
int end = partitioner.getDocument().getLineOfOffset(p.getOffset()+p.getLength()-1);
if ( fAutoScroll ) {
// Check if area around this line is visible, scroll if needed
int top = getTopIndex();
int bottom = getBottomIndex();
if ( start < top + 1 ) {
setTopIndex(start - 1 > 0 ? start - 1 : 0);
} else if ( end > bottom -1 ) {
setTopIndex(top + start - bottom + 1);
}
}
// Select line
StyledText st = getTextWidget();
st.redrawRange(0, partitioner.getDocument().getLength(), true);
} catch (BadLocationException e) {
CUIPlugin.log(e);
}
}
public void mouseEnter(MouseEvent e) {
getTextWidget().addMouseListener(this);
}
public void mouseExit(MouseEvent e) {
getTextWidget().removeMouseListener(this);
}
public void mouseHover(MouseEvent e) {
}
public void mouseDoubleClick(MouseEvent e) {
int offset = -1;
try {
Point p = new Point(e.x, e.y);
offset = getTextWidget().getOffsetAtLocation(p);
BuildConsole.getPage().moveToError(offset);
} catch (IllegalArgumentException ex) {
}
}
public void mouseDown(MouseEvent e) {
}
public void mouseUp(MouseEvent e) {
}
public void lineGetBackground(LineBackgroundEvent event) {
IDocument document = getDocument();
if (document == null) return;
BuildConsolePartitioner partitioner = (BuildConsolePartitioner) document.getDocumentPartitioner();
if (partitioner == null) return;
BuildConsolePartition partition = (BuildConsolePartition) partitioner.getPartition(event.lineOffset);
// Set background for error partitions
if ( partition != null && partition.getType() == BuildConsolePartition.ERROR_PARTITION_TYPE ) {
event.lineBackground = partitioner.fManager.getProblemBackgroundColor();
}
}

View file

@ -0,0 +1,56 @@
/*******************************************************************************
* Copyright (c) 2002, 2010 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
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
import java.io.IOException;
import org.eclipse.cdt.core.ConsoleOutputStream;
import org.eclipse.cdt.core.ProblemMarkerInfo;
import org.eclipse.cdt.internal.core.IErrorMarkeredOutputStream;
/**
* Output stream which put all output to BuildConsolePartitioner
* and informs it when stream is closed
*/
public class BuildOutputStream extends ConsoleOutputStream implements IErrorMarkeredOutputStream {
final BuildConsoleStreamDecorator fStream;
private BuildConsolePartitioner fPartitioner;
public BuildOutputStream(BuildConsolePartitioner partitioner,
BuildConsoleStreamDecorator stream) {
fPartitioner = partitioner;
fStream = stream;
}
@Override
public void flush() throws IOException {
}
@Override
public void close() throws IOException {
flush();
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
fPartitioner.appendToDocument(new String(b, off, len), fStream, null);
}
public void write(String s, ProblemMarkerInfo marker) throws IOException {
fPartitioner.appendToDocument(s, fStream, marker);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2002, 2008 QNX Software Systems and others.
* Copyright (c) 2002, 2010 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
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
@ -29,6 +30,9 @@ public final class ConsoleMessages extends NLS {
public static String BuildConsolePage_Select__All_Ctrl_A_12;
public static String BuildConsolePage_Select_All;
public static String ScrollLockAction_Scroll_Lock_1;
public static String PreviousErrorAction_Tooltip;
public static String NextErrorAction_Tooltip;
public static String ShowErrorAction_Tooltip;
static {
NLS.initializeMessages(BUNDLE_NAME, ConsoleMessages.class);

View file

@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2003, 2008 QNX Software Systems and others.
# Copyright (c) 2003, 2010 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
@ -20,3 +20,7 @@ BuildConsolePage_Select__All_Ctrl_A_12=Select &All@Ctrl+A
BuildConsolePage_Select_All=Select All
ScrollLockAction_Scroll_Lock_1=Scroll Lock
NextErrorAction_Tooltip=&Next Error
PreviousErrorAction_Tooltip=&Previous Error
ShowErrorAction_Tooltip=&Show Error In Editor

View file

@ -0,0 +1,119 @@
/*******************************************************************************
* Copyright (c) 2010 CodeSourcery 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:
* Dmitry Kozlov (CodeSourcery) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.cdt.core.ProblemMarkerInfo;
/**
* Manages current position of highlighted error in BuildConsole
*/
class DocumentMarkerManager {
BuildConsoleDocument fDocument;
BuildConsolePartitioner fPartitioner;
int highlightedPartitionIndex = -1;
DocumentMarkerManager(BuildConsoleDocument document, BuildConsolePartitioner partitioner) {
fDocument = document;
fPartitioner = partitioner;
}
/** Increment index */
void moveToNextError() {
if ( fPartitioner.fPartitions.size() == 0 ) return;
if ( highlightedPartitionIndex == -1 ) {
moveToFirstError();
return;
}
int i = highlightedPartitionIndex + 1;
do {
if ( i == fPartitioner.fPartitions.size() ) {
i = 0;
}
if ( fPartitioner.fPartitions.get(i).getType() == BuildConsolePartition.ERROR_PARTITION_TYPE ) {
highlightedPartitionIndex = i;
return;
} else {
i++;
}
} while ( highlightedPartitionIndex != i);
}
/** Decrement index */
void moveToPreviousError() {
if ( fPartitioner.fPartitions.size() == 0 ) return;
if ( highlightedPartitionIndex == -1 ) {
moveToFirstError();
return;
}
int i = highlightedPartitionIndex - 1;
do {
if ( i == -1 ) {
i = fPartitioner.fPartitions.size() - 1;
}
if ( fPartitioner.fPartitions.get(i).getType() == BuildConsolePartition.ERROR_PARTITION_TYPE ) {
highlightedPartitionIndex = i;
return;
} else {
i--;
}
} while ( highlightedPartitionIndex != i);
}
void moveToFirstError() {
for (int i=0; i<fPartitioner.fPartitions.size(); i++) {
if ( fPartitioner.fPartitions.get(i).getType() == BuildConsolePartition.ERROR_PARTITION_TYPE ) {
highlightedPartitionIndex = i;
return;
}
}
highlightedPartitionIndex = -1;
}
/** Returns true if offset points to error partition and false otherwise */
boolean moveToErrorByOffset(int offset) {
ITypedRegion p = fPartitioner.getPartition(offset);
if ( BuildConsolePartition.ERROR_PARTITION_TYPE.equals(p.getType()) ) {
highlightedPartitionIndex = fPartitioner.fPartitions.indexOf(p);
return true;
}
return false;
}
/** Get marker for current error */
ProblemMarkerInfo getCurrentErrorMarker() {
BuildConsolePartition p = getCurrentPartition();
if ( p != null ) {
return p.getMarker();
} else {
return null;
}
}
/** Get partition for current error */
BuildConsolePartition getCurrentPartition() {
if ( 0 <= highlightedPartitionIndex &&
highlightedPartitionIndex < fPartitioner.fPartitions.size() ) {
BuildConsolePartition p = (BuildConsolePartition)fPartitioner.fPartitions.get(highlightedPartitionIndex);
return p;
}
return null;
}
void clear() {
highlightedPartitionIndex = -1;
}
}

View file

@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2010 CodeSourcery 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:
* Dmitry Kozlov (CodeSourcery) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
import org.eclipse.jface.action.Action;
import org.eclipse.cdt.internal.ui.CPluginImages;
/**
* Advance console document to the next error reported by compiler
*/
public class NextErrorAction extends Action {
private BuildConsolePage fConsolePage;
public NextErrorAction(BuildConsolePage page) {
super(ConsoleMessages.NextErrorAction_Tooltip);
fConsolePage = page;
setEnabled(true);
setToolTipText(ConsoleMessages.NextErrorAction_Tooltip);
CPluginImages.setImageDescriptors(this, CPluginImages.T_LCL, CPluginImages.IMG_SHOW_NEXT);
}
/**
* @see org.eclipse.jface.action.IAction#run()
*/
@Override
public void run() {
fConsolePage.moveToError(BuildConsolePage.POSITION_NEXT);
}
}

View file

@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2010 CodeSourcery 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:
* Dmitry Kozlov (CodeSourcery) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
import org.eclipse.jface.action.Action;
import org.eclipse.cdt.internal.ui.CPluginImages;
/**
* Retard console document to the previous error reported by compiler
*/
public class PreviousErrorAction extends Action {
private BuildConsolePage fConsolePage;
public PreviousErrorAction(BuildConsolePage page) {
super(ConsoleMessages.NextErrorAction_Tooltip);
fConsolePage = page;
setEnabled(true);
setToolTipText(ConsoleMessages.PreviousErrorAction_Tooltip);
CPluginImages.setImageDescriptors(this, CPluginImages.T_LCL, CPluginImages.IMG_SHOW_PREV);
}
/**
* @see org.eclipse.jface.action.IAction#run()
*/
@Override
public void run() {
fConsolePage.moveToError(BuildConsolePage.POSITION_PREV);
}
}

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2010 CodeSourcery 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:
* Dmitry Kozlov (CodeSourcery) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.buildconsole;
import org.eclipse.jface.action.Action;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
/**
* Set whether to show error in editor when moving to next/prev error in Build Console
*/
public class ShowErrorAction extends Action {
public ShowErrorAction() {
super(ConsoleMessages.ShowErrorAction_Tooltip);
setChecked(true);
setToolTipText(ConsoleMessages.ShowErrorAction_Tooltip);
ISharedImages images = PlatformUI.getWorkbench().getSharedImages();
setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_ELCL_SYNCED));
setDisabledImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_ELCL_SYNCED_DISABLED));
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2006 QNX Software Systems and others.
* Copyright (c) 2000, 2010 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
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
@ -40,6 +41,8 @@ public class BuildConsolePreferencePage extends FieldEditorPreferencePage implem
public static final String PREF_BUILDCONSOLE_OUTPUT_COLOR = "buildConsoleOutputStreamColor"; //$NON-NLS-1$
public static final String PREF_BUILDCONSOLE_ERROR_COLOR = "buildConsoleErrorStreamColor"; //$NON-NLS-1$
public static final String PREF_BUILDCONSOLE_BACKGROUND_COLOR = "buildConsoleBackgroundColor"; //$NON-NLS-1$
public static final String PREF_BUILDCONSOLE_PROBLEM_BACKGROUND_COLOR = "buildConsoleProblemBackgroundColor"; //$NON-NLS-1$
public static final String PREF_BUILDCONSOLE_PROBLEM_HIGHLIGHTED_COLOR = "buildConsoleProblemHighlightedColor"; //$NON-NLS-1$
public BuildConsolePreferencePage() {
super(GRID);
@ -82,6 +85,10 @@ public class BuildConsolePreferencePage extends FieldEditorPreferencePage implem
CUIPlugin.getResourceString("ConsolePreferencePage.errorColor.label"), parent)); //$NON-NLS-1$
addField(createColorFieldEditor(PREF_BUILDCONSOLE_BACKGROUND_COLOR,
CUIPlugin.getResourceString("ConsolePreferencePage.backgroundColor.label"), parent)); //$NON-NLS-1$
addField(createColorFieldEditor(PREF_BUILDCONSOLE_PROBLEM_BACKGROUND_COLOR,
CUIPlugin.getResourceString("ConsolePreferencePage.problemBackgroundColor.label"), parent)); //$NON-NLS-1$
addField(createColorFieldEditor(PREF_BUILDCONSOLE_PROBLEM_HIGHLIGHTED_COLOR,
CUIPlugin.getResourceString("ConsolePreferencePage.problemHighlightedColor.label"), parent)); //$NON-NLS-1$
}
private Label createLabel(Composite parent, String text) {
@ -135,6 +142,8 @@ public class BuildConsolePreferencePage extends FieldEditorPreferencePage implem
PreferenceConverter.setDefault(prefs, PREF_BUILDCONSOLE_INFO_COLOR, new RGB(0, 0, 255));
PreferenceConverter.setDefault(prefs, PREF_BUILDCONSOLE_ERROR_COLOR, new RGB(255, 0, 0));
PreferenceConverter.setDefault(prefs, PREF_BUILDCONSOLE_BACKGROUND_COLOR, new RGB(255, 255, 255));
PreferenceConverter.setDefault(prefs, PREF_BUILDCONSOLE_PROBLEM_BACKGROUND_COLOR, new RGB(254, 231, 224));
PreferenceConverter.setDefault(prefs, PREF_BUILDCONSOLE_PROBLEM_HIGHLIGHTED_COLOR, new RGB(255, 0, 0));
}
}