From d017af2e853e54915c393101b0fe729bf2da21a5 Mon Sep 17 00:00:00 2001 From: Anton Leherbauer Date: Wed, 30 Aug 2006 08:52:24 +0000 Subject: [PATCH] Add unit test for inactive code highlighting --- .../resources/inactiveCode/InactiveCodeTest.c | 72 ++++++++++ .../eclipse/cdt/ui/tests/AutomatedSuite.java | 5 +- .../text/InactiveCodeHighlightingTest.java | 127 ++++++++++++++++++ .../internal/ui/LineBackgroundPainter.java | 8 ++ .../ui/editor/InactiveCodeHighlighting.java | 19 +-- 5 files changed, 221 insertions(+), 10 deletions(-) create mode 100644 core/org.eclipse.cdt.ui.tests/resources/inactiveCode/InactiveCodeTest.c create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/InactiveCodeHighlightingTest.java diff --git a/core/org.eclipse.cdt.ui.tests/resources/inactiveCode/InactiveCodeTest.c b/core/org.eclipse.cdt.ui.tests/resources/inactiveCode/InactiveCodeTest.c new file mode 100644 index 00000000000..43a422f843b --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/inactiveCode/InactiveCodeTest.c @@ -0,0 +1,72 @@ +#define foo 0 + +#if 0 +# define NEVER_DEFINED +#endif + +// X is defined +#define X + +#ifdef X +# define X_IS_DEFINED +# if 0 + // always disabled +# endif +# define X_IS_IT +#elif defined (Y) +# define Y_IS_DEFINED_BUT_NOT_X +# if 1 + // always enabled if outer branch enabled +# endif +#else +# define NEITHER_X_NOR_Y_IS_DEFINED +#endif + +// X is not defined, Y is defined +#undef X +#define Y + +#ifdef X +# define X_IS_DEFINED +# if 0 + // always disabled +# endif +# define X_IS_IT +#elif defined (Y) +# define Y_IS_DEFINED_BUT_NOT_X +# if 1 + // always enabled if outer branch enabled +# endif +#else +# define NEITHER_X_NOR_Y_IS_DEFINED +#endif + +// X is not defined, Y is not defined +#undef X +#undef Y + +#ifdef X +# define X_IS_DEFINED +# if 0 + // always disabled +# endif +# define X_IS_IT +#elif defined (Y) +# define Y_IS_DEFINED_BUT_NOT_X +# if 1 + // always enabled if outer branch enabled +# endif +#else +# define NEITHER_X_NOR_Y_IS_DEFINED +#endif + +#ifndef F +#ifdef // this gives an error +#error invalid ifdef +#endif + +#if foo +//my code +#endif + +#endif // unbalanced endif because of invalid ifdef above diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java index 74a3980f805..984334556cc 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java @@ -7,7 +7,7 @@ * * Contributors: * IBM - Initial API and implementation - * Anton Leherbauer (Wind River Systems) - Fixed bug 48339 + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.ui.tests; @@ -18,6 +18,7 @@ import org.eclipse.cdt.ui.tests.text.CAutoIndentTest; import org.eclipse.cdt.ui.tests.text.CBreakIteratorTest; import org.eclipse.cdt.ui.tests.text.CPartitionerTest; import org.eclipse.cdt.ui.tests.text.CWordIteratorTest; +import org.eclipse.cdt.ui.tests.text.InactiveCodeHighlightingTest; import org.eclipse.cdt.ui.tests.text.NumberRuleTest; import org.eclipse.cdt.ui.tests.text.SemanticHighlightingTest; import org.eclipse.cdt.ui.tests.text.contentassist.CompletionFailedTest_MemberReference_Arrow_Prefix2; @@ -149,7 +150,7 @@ public class AutomatedSuite extends TestSuite { // highlighting tests addTest(SemanticHighlightingTest.suite()); - + addTest(InactiveCodeHighlightingTest.suite()); } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/InactiveCodeHighlightingTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/InactiveCodeHighlightingTest.java new file mode 100644 index 00000000000..a50974443f3 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/InactiveCodeHighlightingTest.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems, Inc. 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: + * Anton Leherbauer (Wind River Systems) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.ui.tests.text; + +import java.util.List; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor; + +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; + +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.editor.CSourceViewerDecorationSupport; +import org.eclipse.cdt.internal.ui.editor.InactiveCodeHighlighting; + +/** + * Tests for inactive code highlighting. + * + * @since 4.0 + */ +public class InactiveCodeHighlightingTest extends TestCase { + + private static final String LINKED_FOLDER= "resources/inactiveCode"; + private static final String PROJECT= "InactiveCodeTest"; + + private ICProject fCProject; + private final String fTestFilename= "/InactiveCodeTest/src/InactiveCodeTest.c"; + + private static CEditor fEditor; + + private static SourceViewer fSourceViewer; + + public static Test suite() { + return new TestSuite(InactiveCodeHighlightingTest.class); + } + + public InactiveCodeHighlightingTest(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + fCProject= EditorTestHelper.createCProject(PROJECT, LINKED_FOLDER); + + fEditor= (CEditor) EditorTestHelper.openInEditor(ResourceTestHelper.findFile(fTestFilename), true); + fSourceViewer= EditorTestHelper.getSourceViewer(fEditor); + assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100)); + } + + protected void tearDown () throws Exception { + EditorTestHelper.closeEditor(fEditor); + + if (fCProject != null) + CProjectHelper.delete(fCProject); + + super.tearDown(); + } + + protected void assertEqualPositions(Position[] expected, Position[] actual) { + assertEquals(expected.length, actual.length); + for (int i= 0, n= expected.length; i < n; i++) { + assertEquals(expected[i].isDeleted(), actual[i].isDeleted()); + assertEquals(expected[i].getOffset(), actual[i].getOffset()); + assertEquals(expected[i].getLength(), actual[i].getLength()); + } + } + + protected Position createPosition(int line, int column, int length) throws BadLocationException { + IDocument document= fSourceViewer.getDocument(); + return new Position(document.getLineOffset(line) + column, length); + } + + String toString(Position[] positions) throws BadLocationException { + StringBuffer buf= new StringBuffer(); + IDocument document= fSourceViewer.getDocument(); + buf.append("Position[] expected= new Position[] {\n"); + for (int i= 0, n= positions.length; i < n; i++) { + Position position= positions[i]; + int line= document.getLineOfOffset(position.getOffset()); + int column= position.getOffset() - document.getLineOffset(line); + buf.append("\tcreatePosition(" + line + ", " + column + ", " + position.getLength() + "),\n"); + } + buf.append("};\n"); + return buf.toString(); + } + + protected Position[] getInactiveCodePositions() { + CSourceViewerDecorationSupport support= (CSourceViewerDecorationSupport) new Accessor(fEditor, AbstractDecoratedTextEditor.class).get("fSourceViewerDecorationSupport"); + InactiveCodeHighlighting highlighting= (InactiveCodeHighlighting) new Accessor(support, support.getClass()).get("fInactiveCodeHighlighting"); + List positions= (List) new Accessor(highlighting, highlighting.getClass()).get("fInactiveCodePositions"); + return (Position[]) positions.toArray(new Position[positions.size()]); + } + + + public void testInactiveCodePositions() throws BadLocationException { + Position[] actual= getInactiveCodePositions(); + Position[] expected= new Position[] { + createPosition(2, 0, 37), + createPosition(11, 0, 37), + createPosition(15, 0, 164), + createPosition(28, 0, 107), + createPosition(39, 0, 50), + createPosition(47, 0, 209), + createPosition(67, 0, 26), + }; + if (false) System.out.println(toString(actual)); + assertEqualPositions(expected, actual); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/LineBackgroundPainter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/LineBackgroundPainter.java index 829c5e912e1..aceda024690 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/LineBackgroundPainter.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/LineBackgroundPainter.java @@ -242,6 +242,14 @@ public class LineBackgroundPainter implements IPainter, LineBackgroundListener { fColorMap= null; } + /** + * Query whether this painter is already disposed. + * @return true if the painter is disposed + */ + public boolean isDisposed() { + return fTextViewer == null; + } + /* * @see org.eclipse.jface.text.IPainter#paint(int) */ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/InactiveCodeHighlighting.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/InactiveCodeHighlighting.java index 227ee771d7a..7ce2a91e7df 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/InactiveCodeHighlighting.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/InactiveCodeHighlighting.java @@ -43,8 +43,10 @@ import org.eclipse.cdt.internal.ui.LineBackgroundPainter; import org.eclipse.cdt.internal.ui.text.ICReconcilingListener; /** - * TLETODO Document InactiveCodeHighlighting. - * + * Paints code lines disabled by preprocessor directives (#ifdef etc.) + * with a configurable background color (default light gray). + * + * @see LineBackgroundPainter * @since 4.0 */ public class InactiveCodeHighlighting implements ICReconcilingListener { @@ -108,13 +110,14 @@ public class InactiveCodeHighlighting implements ICReconcilingListener { fUpdateJob.setPriority(Job.DECORATE); } if (fUpdateJob.getState() == Job.NONE) { - // schedule later if AST is not available yet fUpdateJob.schedule(); } } } /** + * Install this highlighting on the given editor. + * * @param editor */ public void install(CEditor editor) { @@ -130,7 +133,7 @@ public class InactiveCodeHighlighting implements ICReconcilingListener { } /** - * + * Uninstall this highlighting from the editor. Does nothing if already uninstalled. */ public void uninstall() { if (fLineBackgroundPainter != null) { @@ -145,8 +148,8 @@ public class InactiveCodeHighlighting implements ICReconcilingListener { } public void dispose() { - fLineBackgroundPainter= null; uninstall(); + fLineBackgroundPainter= null; } /** @@ -178,7 +181,7 @@ public class InactiveCodeHighlighting implements ICReconcilingListener { } Runnable updater = new Runnable() { public void run() { - if (fEditor != null && fLineBackgroundPainter != null) { + if (fEditor != null && fLineBackgroundPainter != null && !fLineBackgroundPainter.isDisposed()) { fLineBackgroundPainter.replaceHighlightPositions(fInactiveCodePositions, newInactiveCodePositions); fInactiveCodePositions= newInactiveCodePositions; } @@ -255,7 +258,7 @@ public class InactiveCodeHighlighting implements ICReconcilingListener { inInactiveCode = true; } else if (elseStmt.taken() && inInactiveCode) { IASTNodeLocation nodeLocation = elseStmt.getNodeLocations()[0]; - int inactiveCodeEnd = nodeLocation.getNodeOffset() - 1; + int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength(); positions.add(new HighlightPosition(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart, fHighlightKey)); inInactiveCode = false; } @@ -267,7 +270,7 @@ public class InactiveCodeHighlighting implements ICReconcilingListener { inInactiveCode = true; } else if (elifStmt.taken() && inInactiveCode) { IASTNodeLocation nodeLocation = elifStmt.getNodeLocations()[0]; - int inactiveCodeEnd = nodeLocation.getNodeOffset() - 1; + int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength(); positions.add(new HighlightPosition(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart, fHighlightKey)); inInactiveCode = false; }