From 7412f600a8316ec6f9ddfe7000ab6630bd35f69f Mon Sep 17 00:00:00 2001 From: Anton Leherbauer Date: Fri, 29 Sep 2006 15:36:10 +0000 Subject: [PATCH] Reworked syntax highlighting of preprocessor directives --- .../cdt/ui/tests}/text/CPartitionScanner.java | 2 +- .../cdt/ui/tests/text/CPartitionerTest.java | 572 +++++++++++------- .../tests/text/PartitionTokenScannerTest.java | 5 +- .../tests/text/SemanticHighlightingTest.java | 2 +- .../cdt/ui/tests/text/TextTestSuite.java | 2 +- core/org.eclipse.cdt.ui/plugin.xml | 2 +- .../ui/actions/AddBlockCommentAction.java | 4 +- .../cdt/internal/ui/editor/CSourceViewer.java | 23 + .../ui/editor/asm/AsmPreprocessorScanner.java | 117 ++++ .../asm/AsmSourceViewerConfiguration.java | 19 +- .../internal/ui/editor/asm/AsmTextTools.java | 33 +- .../CEditorColoringConfigurationBlock.java | 17 +- .../ui/preferences/PreferencesMessages.java | 6 +- .../PreferencesMessages.properties | 6 +- .../cdt/internal/ui/text/CCodeScanner.java | 19 +- .../cdt/internal/ui/text/CHeaderRule.java | 10 +- .../ui/text/CPreprocessorScanner.java | 145 +++++ .../ui/text/CSourceViewerConfiguration.java | 37 +- .../cdt/internal/ui/text/CTextTools.java | 44 +- .../cdt/internal/ui/text/CppCodeScanner.java | 20 +- .../ui/text/FastCPartitionScanner.java | 444 ++++++++++---- .../internal/ui/text/ICColorConstants.java | 32 +- .../internal/ui/text/PartitionDamager.java | 42 ++ .../internal/ui/text/PreprocessorRule.java | 71 ++- .../ui/text/util/CWhitespaceDetector.java | 19 +- .../eclipse/cdt/ui/PreferenceConstants.java | 146 +++-- .../org/eclipse/cdt/ui/text/ICPartitions.java | 5 + 27 files changed, 1364 insertions(+), 480 deletions(-) rename core/{org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui => org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests}/text/CPartitionScanner.java (98%) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmPreprocessorScanner.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPreprocessorScanner.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/PartitionDamager.java diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPartitionScanner.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CPartitionScanner.java similarity index 98% rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPartitionScanner.java rename to core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CPartitionScanner.java index 87594c786b4..de63bf98a37 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPartitionScanner.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CPartitionScanner.java @@ -9,7 +9,7 @@ * IBM Corporation - initial API and implementation * QNX Software System *******************************************************************************/ -package org.eclipse.cdt.internal.ui.text; +package org.eclipse.cdt.ui.tests.text; import java.util.ArrayList; import java.util.List; diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CPartitionerTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CPartitionerTest.java index 6379019245b..6589b7d8fa3 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CPartitionerTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CPartitionerTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 2006 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.ui.tests.text; @@ -33,42 +34,42 @@ import org.eclipse.cdt.internal.ui.text.CTextTools; * Derived from JavaPartitionerTest. */ public class CPartitionerTest extends TestCase { - + private CTextTools fTextTools; private Document fDocument; protected boolean fDocumentPartitioningChanged; - - + + public CPartitionerTest(String name) { super(name); } - + protected void setUp() { fTextTools= new CTextTools(new PreferenceStore()); - + fDocument= new Document(); IDocumentPartitioner partitioner= fTextTools.createDocumentPartitioner(); partitioner.connect(fDocument); fDocument.setDocumentPartitioner(partitioner); fDocument.set("xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/***/\nxxx"); - + fDocumentPartitioningChanged= false; fDocument.addDocumentPartitioningListener(new IDocumentPartitioningListener() { public void documentPartitioningChanged(IDocument document) { fDocumentPartitioningChanged= true; } - }); + }); } - + public static Test suite() { - return new TestSuite(CPartitionerTest.class); + return new TestSuite(CPartitionerTest.class); } - + protected void tearDown () { fTextTools.dispose(); fTextTools= null; - + IDocumentPartitioner partitioner= fDocument.getDocumentPartitioner(); partitioner.disconnect(); fDocument= null; @@ -77,24 +78,24 @@ public class CPartitionerTest extends TestCase { protected String print(ITypedRegion r) { return "[" + r.getOffset() + "," + r.getLength() + "," + r.getType() + "]"; } - + protected void checkPartitioning(ITypedRegion[] expectation, ITypedRegion[] result) { - + assertEquals("invalid number of partitions", expectation.length, result.length); - + for (int i= 0; i < expectation.length; i++) { ITypedRegion e= expectation[i]; ITypedRegion r= result[i]; assertTrue(print(r) + " != " + print(e), r.equals(e)); } - + } - + public void testInitialPartitioning() { try { - + // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/***/\nxxx" - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -107,21 +108,21 @@ public class CPartitionerTest extends TestCase { new TypedRegion(38, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(43, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); } } - + public void testIntraPartitionChange() { try { - + fDocument.replace(34, 3, "y"); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\ny\n/***/\nxxx"); - + assertTrue(!fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -134,21 +135,21 @@ public class CPartitionerTest extends TestCase { new TypedRegion(36, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(41, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); - } + } } public void testIntraPartitionChange2() { try { - + fDocument.replace(41, 0, "yyy"); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/**yyy*/\nxxx"); - + // assertTrue(!fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -161,20 +162,20 @@ public class CPartitionerTest extends TestCase { new TypedRegion(38, 8, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(46, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); - } + } } public void testInsertNewPartition() { try { - + fDocument.replace(35, 1, "/***/"); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nx/***/x\n/***/\nxxx"); - + assertTrue(fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -189,20 +190,20 @@ public class CPartitionerTest extends TestCase { new TypedRegion(42, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(47, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); - } - } + } + } public void testInsertStringPartition() { try { - + fDocument.replace(35, 1, "\"yyy\""); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nx\"yyy\"x\n/***/\nxxx"); - + assertTrue(fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -217,20 +218,20 @@ public class CPartitionerTest extends TestCase { new TypedRegion(42, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(47, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); - } - } + } + } public void testInsertCharacterPartition() { try { - + fDocument.replace(35, 1, "'y'"); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nx\"yyy\"x\n/***/\nxxx"); - + assertTrue(fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -245,22 +246,50 @@ public class CPartitionerTest extends TestCase { new TypedRegion(40, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(45, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); - } - } + } + } + public void testInsertPreprocessorPartition() { + try { + + fDocument.replace(4, 0, " # include \n"); + // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nx\"yyy\"x\n/***/\nxxx"); + // "xxx\n # include \n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nx\"yyy\"x\n/***/\nxxx"); + + assertTrue(fDocumentPartitioningChanged); + + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); + TypedRegion[] expectation= { + new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(4, 17, ICPartitions.C_PREPROCESSOR), + new TypedRegion(21, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(28, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(33, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(41, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(46, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(50, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(55, 5, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(60, 4, IDocument.DEFAULT_CONTENT_TYPE) + }; + + checkPartitioning(expectation, result); + } catch (BadLocationException x) { + assertTrue(false); + } + } public void testRemovePartition1() { try { - + fDocument.replace(13, 16, null); // "xxx\n/*xxx*/\nx/**/\nxxx\n/***/\nxxx"); - + assertTrue(fDocumentPartitioningChanged); - - + + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -271,25 +300,25 @@ public class CPartitionerTest extends TestCase { new TypedRegion(22, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(27, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); } } - + public void testRemovePartition2() { - + testJoinPartition3(); fDocumentPartitioningChanged= false; - + try { - + fDocument.replace(5, 2, null); // "xxx\nxxx\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/***/\nxxx" - + assertTrue(fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 12, IDocument.DEFAULT_CONTENT_TYPE), @@ -300,22 +329,22 @@ public class CPartitionerTest extends TestCase { new TypedRegion(34, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(39, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); } } - + public void testJoinPartitions1() { try { - + fDocument.replace(31, 1, null); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/*/\nxxx\n/***/\nxxx" - + assertTrue(fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -326,21 +355,21 @@ public class CPartitionerTest extends TestCase { new TypedRegion(29, 13, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(42, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); } } - + public void testJoinPartitions2() { try { - + fDocument.replace(32, 1, null); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**\nxxx\n/***/\nxxx" - + assertTrue(fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -351,21 +380,21 @@ public class CPartitionerTest extends TestCase { new TypedRegion(29, 13, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(42, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); } } - + public void testJoinPartition3() { try { - + fDocument.replace(9, 2, null); // "xxx\n/*xxx\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/***/\nxxx" - + assertTrue(fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -376,68 +405,68 @@ public class CPartitionerTest extends TestCase { new TypedRegion(36, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(41, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); } } - - + + public void testSplitPartition1() { - + testJoinPartitions1(); fDocumentPartitioningChanged= false; - - + + try { - + // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/*/\nxxx\n/***/\nxxx" fDocument.replace(31, 0, "*"); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/***/\nxxx" - + assertTrue(fDocumentPartitioningChanged); - - + + } catch (BadLocationException x) { assertTrue(false); } - + testInitialPartitioning(); } - + public void testSplitPartition2() { - + testJoinPartitions2(); fDocumentPartitioningChanged= false; - + try { - + // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**\nxxx\n/***/\nxxx" fDocument.replace(32, 0, "/"); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/***/\nxxx" - + assertTrue(fDocumentPartitioningChanged); - + } catch (BadLocationException x) { assertTrue(false); } - + testInitialPartitioning(); } - + public void testSplitPartition3() { - + fDocumentPartitioningChanged= false; - + try { - + // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/***/\nxxx" fDocument.replace(12, 9, ""); // "xxx\n/*xxx*/\nx*/\nxxx\n/**/\nxxx\n/***/\nxxx" - + assertTrue(fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -448,27 +477,27 @@ public class CPartitionerTest extends TestCase { new TypedRegion(29, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(34, 4, IDocument.DEFAULT_CONTENT_TYPE) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); } } - + public void testCorruptPartitioning1() { try { - + fDocument.replace(0, fDocument.getLength(), "/***/\n/***/"); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(5, 1, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(6, 5, ICPartitions.C_MULTI_LINE_COMMENT) }; - + checkPartitioning(expectation, result); - + fDocument.replace(6, 0, "*/\n/***/\n/*"); // "/***/\n*/\n/***/\n/*/***/" @@ -479,18 +508,18 @@ public class CPartitionerTest extends TestCase { new TypedRegion(9, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(14, 1, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(15, 7, ICPartitions.C_MULTI_LINE_COMMENT) - }; - + }; + } catch (BadLocationException x) { assertTrue(false); - } + } } - + public void testCorruptPartitioning2() { try { - + fDocument.replace(0, fDocument.getLength(), "/***/\n/***/\n/***/"); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 5, ICPartitions.C_MULTI_LINE_COMMENT), @@ -499,9 +528,9 @@ public class CPartitionerTest extends TestCase { new TypedRegion(11, 1, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(12, 5, ICPartitions.C_MULTI_LINE_COMMENT) }; - + checkPartitioning(expectation, result); - + fDocument.replace(6, 0, "*/\n/***/\n/*"); // "/***/\n*/\n/***/\n/*/***/\n/***/" @@ -514,27 +543,27 @@ public class CPartitionerTest extends TestCase { new TypedRegion(15, 7, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(22, 1, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(23, 5, ICPartitions.C_MULTI_LINE_COMMENT) - }; - + }; + } catch (BadLocationException x) { assertTrue(false); - } + } } - + public void testCorruptPartitioning3() { try { - + fDocument.replace(0, fDocument.getLength(), "/***/\n/**/"); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(5, 1, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(6, 4, ICPartitions.C_MULTI_LINE_COMMENT) }; - + checkPartitioning(expectation, result); - + fDocument.replace(0, 9, "/***/\n/***/\n/***/\n/**"); // "/***/\n/***/\n/***/\n/***/" @@ -547,22 +576,22 @@ public class CPartitionerTest extends TestCase { new TypedRegion(12, 5, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(17, 1, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(18, 5, ICPartitions.C_MULTI_LINE_COMMENT) - }; - + }; + } catch (BadLocationException x) { assertTrue(false); - } + } } public void testOpenPartition1() { try { - + fDocument.replace(42, 1, null); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/***\nxxx" - + assertTrue(fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -574,22 +603,22 @@ public class CPartitionerTest extends TestCase { new TypedRegion(33, 5, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(38, 8, ICPartitions.C_MULTI_LINE_COMMENT) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); } } - + public void testOpenPartition2() { try { - + fDocument.replace(47, 0, "/*"); // "xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/***/\nxxx/*" - + assertTrue(fDocumentPartitioningChanged); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 4, IDocument.DEFAULT_CONTENT_TYPE), @@ -603,19 +632,19 @@ public class CPartitionerTest extends TestCase { new TypedRegion(43, 4, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(47, 2, ICPartitions.C_MULTI_LINE_COMMENT) }; - + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); } } - - + + public void testPartitionFinder() { try { - + ITypedRegion[] partitioning= fDocument.computePartitioning(0, fDocument.getLength()); - + for (int i= 0; i < partitioning.length; i++) { ITypedRegion expected= partitioning[i]; for (int j= 0; j < expected.getLength(); j++) { @@ -623,40 +652,40 @@ public class CPartitionerTest extends TestCase { assertTrue(expected.equals(result)); } } - + } catch (BadLocationException x) { assertTrue(false); } } - + public void testExtendPartition() { try { - + fDocument.replace(0, fDocument.getLength(), "/*"); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 2, ICPartitions.C_MULTI_LINE_COMMENT) }; - + checkPartitioning(expectation, result); - + fDocument.replace(2, 0, " "); result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, 3, ICPartitions.C_MULTI_LINE_COMMENT) }; - + checkPartitioning(expectation, result); - + } catch (BadLocationException x) { assertTrue(false); } } - + public void testTogglePartition() { try { - + fDocument.replace(0, fDocument.getLength(), "\t/*\n\tx\n\t/*/\n\ty\n//\t*/"); ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); @@ -665,119 +694,119 @@ public class CPartitionerTest extends TestCase { new TypedRegion(1, 10, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(11, 4, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(15, 5, ICPartitions.C_SINGLE_LINE_COMMENT) - }; + }; checkPartitioning(expectation1, result); - + fDocumentPartitioningChanged= false; fDocument.replace(0, 0, "//"); // "//\t/*\n\tx\n\t/*/\n\ty\n//\t*/" assertTrue(fDocumentPartitioningChanged); - + result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation2= { new TypedRegion(0, 6, ICPartitions.C_SINGLE_LINE_COMMENT), new TypedRegion(6, 4, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(10, 12, ICPartitions.C_MULTI_LINE_COMMENT) - }; + }; checkPartitioning(expectation2, result); - + } catch (BadLocationException x) { assertTrue(false); } } - + public void testEditing1() { try { - + fDocument.replace(0, fDocument.getLength(), ""); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 0, IDocument.DEFAULT_CONTENT_TYPE) - }; + }; checkPartitioning(expectation, result); - + fDocument.replace(fDocument.getLength(), 0, "/"); fDocument.replace(fDocument.getLength(), 0, "*"); fDocument.replace(fDocument.getLength(), 0, "*"); fDocument.replace(fDocument.getLength(), 0, "/"); - + result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, fDocument.getLength(), ICPartitions.C_MULTI_LINE_COMMENT) - }; - checkPartitioning(expectation, result); - - + }; + checkPartitioning(expectation, result); + + fDocument.replace(fDocument.getLength(), 0, "\r\n"); result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, 4, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(4, 2, IDocument.DEFAULT_CONTENT_TYPE) - }; - checkPartitioning(expectation, result); - - + }; + checkPartitioning(expectation, result); + + } catch (BadLocationException x) { assertTrue(false); } } - + public void testEditing2() { try { - + fDocument.replace(0, fDocument.getLength(), ""); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 0, IDocument.DEFAULT_CONTENT_TYPE) - }; + }; checkPartitioning(expectation, result); - + fDocument.replace(fDocument.getLength(), 0, "/"); fDocument.replace(fDocument.getLength(), 0, "*"); result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, fDocument.getLength(), ICPartitions.C_MULTI_LINE_COMMENT) - }; - checkPartitioning(expectation, result); - + }; + checkPartitioning(expectation, result); + fDocument.replace(fDocument.getLength(), 0, "\r\n"); result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, fDocument.getLength(), ICPartitions.C_MULTI_LINE_COMMENT) - }; + }; checkPartitioning(expectation, result); - + fDocument.replace(fDocument.getLength(), 0, "*"); result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, fDocument.getLength(), ICPartitions.C_MULTI_LINE_COMMENT) - }; + }; checkPartitioning(expectation, result); - + fDocument.replace(fDocument.getLength(), 0, "*"); result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, fDocument.getLength(), ICPartitions.C_MULTI_LINE_COMMENT) - }; - checkPartitioning(expectation, result); - + }; + checkPartitioning(expectation, result); + } catch (BadLocationException x) { assertTrue(false); } } - + public void testEditing3() { try { - + fDocument.replace(0, fDocument.getLength(), ""); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 0, IDocument.DEFAULT_CONTENT_TYPE) - }; + }; checkPartitioning(expectation, result); - + fDocument.replace(fDocument.getLength(), 0, "/"); fDocument.replace(fDocument.getLength(), 0, "*"); fDocument.replace(fDocument.getLength(), 0, "*"); @@ -788,17 +817,17 @@ public class CPartitionerTest extends TestCase { result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, fDocument.getLength(), ICPartitions.C_MULTI_LINE_COMMENT) - }; - checkPartitioning(expectation, result); - + }; + checkPartitioning(expectation, result); + fDocument.replace(fDocument.getLength(), 0, "*"); result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, 8, ICPartitions.C_MULTI_LINE_COMMENT), new TypedRegion(8, 1, IDocument.DEFAULT_CONTENT_TYPE) - }; - checkPartitioning(expectation, result); - + }; + checkPartitioning(expectation, result); + } catch (BadLocationException x) { assertTrue(false); } @@ -806,15 +835,15 @@ public class CPartitionerTest extends TestCase { public void testEditingString() { try { - + fDocument.replace(0, fDocument.getLength(), ""); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 0, IDocument.DEFAULT_CONTENT_TYPE) - }; + }; checkPartitioning(expectation, result); - + fDocument.replace(fDocument.getLength(), 0, "\""); fDocument.replace(fDocument.getLength(), 0, "y"); fDocument.replace(fDocument.getLength(), 0, "y"); @@ -823,16 +852,16 @@ public class CPartitionerTest extends TestCase { result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, fDocument.getLength(), ICPartitions.C_STRING) - }; - checkPartitioning(expectation, result); - + }; + checkPartitioning(expectation, result); + fDocument.replace(fDocument.getLength(), 0, "y"); result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, 4, ICPartitions.C_STRING), new TypedRegion(4, 1, IDocument.DEFAULT_CONTENT_TYPE) - }; - checkPartitioning(expectation, result); + }; + checkPartitioning(expectation, result); // insert escaped double quote fDocument.replace(2, 0, "\\\""); @@ -840,8 +869,8 @@ public class CPartitionerTest extends TestCase { expectation= new TypedRegion[] { new TypedRegion(0, 6, ICPartitions.C_STRING), new TypedRegion(6, 1, IDocument.DEFAULT_CONTENT_TYPE) - }; - checkPartitioning(expectation, result); + }; + checkPartitioning(expectation, result); // insert closing and opening double quote fDocument.replace(2, 2, "\"\""); @@ -850,8 +879,8 @@ public class CPartitionerTest extends TestCase { new TypedRegion(0, 3, ICPartitions.C_STRING), new TypedRegion(3, 3, ICPartitions.C_STRING), new TypedRegion(6, 1, IDocument.DEFAULT_CONTENT_TYPE) - }; - checkPartitioning(expectation, result); + }; + checkPartitioning(expectation, result); // insert line continuation and newline fDocument.replace(2, 2, "\\\r\n"); @@ -859,8 +888,8 @@ public class CPartitionerTest extends TestCase { expectation= new TypedRegion[] { new TypedRegion(0, 7, ICPartitions.C_STRING), new TypedRegion(7, 1, IDocument.DEFAULT_CONTENT_TYPE) - }; - checkPartitioning(expectation, result); + }; + checkPartitioning(expectation, result); // delete line continuation fDocument.replace(2, 1, ""); @@ -869,25 +898,25 @@ public class CPartitionerTest extends TestCase { new TypedRegion(0, 4, ICPartitions.C_STRING), new TypedRegion(4, 1, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(5, 2, ICPartitions.C_STRING) - }; - checkPartitioning(expectation, result); + }; + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); } } - + public void testEditingCharacter() { try { - + fDocument.replace(0, fDocument.getLength(), ""); - + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); TypedRegion[] expectation= { new TypedRegion(0, 0, IDocument.DEFAULT_CONTENT_TYPE) - }; + }; checkPartitioning(expectation, result); - + fDocument.replace(fDocument.getLength(), 0, "'"); fDocument.replace(fDocument.getLength(), 0, "y"); fDocument.replace(fDocument.getLength(), 0, "y"); @@ -896,16 +925,16 @@ public class CPartitionerTest extends TestCase { result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, fDocument.getLength(), ICPartitions.C_CHARACTER) - }; - checkPartitioning(expectation, result); - + }; + checkPartitioning(expectation, result); + fDocument.replace(fDocument.getLength(), 0, "y"); result= fDocument.computePartitioning(0, fDocument.getLength()); expectation= new TypedRegion[] { new TypedRegion(0, 4, ICPartitions.C_CHARACTER), new TypedRegion(4, 1, IDocument.DEFAULT_CONTENT_TYPE) - }; - checkPartitioning(expectation, result); + }; + checkPartitioning(expectation, result); // insert escaped single quote fDocument.replace(2, 0, "\\'"); @@ -913,8 +942,8 @@ public class CPartitionerTest extends TestCase { expectation= new TypedRegion[] { new TypedRegion(0, 6, ICPartitions.C_CHARACTER), new TypedRegion(6, 1, IDocument.DEFAULT_CONTENT_TYPE) - }; - checkPartitioning(expectation, result); + }; + checkPartitioning(expectation, result); // insert closing and opening quote fDocument.replace(2, 2, "''"); @@ -923,8 +952,8 @@ public class CPartitionerTest extends TestCase { new TypedRegion(0, 3, ICPartitions.C_CHARACTER), new TypedRegion(3, 3, ICPartitions.C_CHARACTER), new TypedRegion(6, 1, IDocument.DEFAULT_CONTENT_TYPE) - }; - checkPartitioning(expectation, result); + }; + checkPartitioning(expectation, result); // insert line continuation and newline fDocument.replace(2, 2, "\\\r\n"); @@ -932,8 +961,8 @@ public class CPartitionerTest extends TestCase { expectation= new TypedRegion[] { new TypedRegion(0, 7, ICPartitions.C_CHARACTER), new TypedRegion(7, 1, IDocument.DEFAULT_CONTENT_TYPE) - }; - checkPartitioning(expectation, result); + }; + checkPartitioning(expectation, result); // delete line continuation fDocument.replace(2, 1, ""); @@ -942,8 +971,97 @@ public class CPartitionerTest extends TestCase { new TypedRegion(0, 4, ICPartitions.C_CHARACTER), new TypedRegion(4, 1, IDocument.DEFAULT_CONTENT_TYPE), new TypedRegion(5, 2, ICPartitions.C_CHARACTER) - }; - checkPartitioning(expectation, result); + }; + checkPartitioning(expectation, result); + + } catch (BadLocationException x) { + assertTrue(false); + } + } + + public void testEditingPreprocessor() { + try { + + fDocument.replace(0, fDocument.getLength(), ""); + + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); + TypedRegion[] expectation= { + new TypedRegion(0, 0, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + fDocument.replace(fDocument.getLength(), 0, "#"); + fDocument.replace(fDocument.getLength(), 0, " "); + fDocument.replace(fDocument.getLength(), 0, "\t"); + fDocument.replace(fDocument.getLength(), 0, "include /* */"); + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, fDocument.getLength(), ICPartitions.C_PREPROCESSOR) + }; + checkPartitioning(expectation, result); + + fDocument.replace(fDocument.getLength(), 0, "\nz"); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 27, ICPartitions.C_PREPROCESSOR), + new TypedRegion(27, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + // insert escaped backslash + fDocument.replace(2, 0, "\\\\"); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 29, ICPartitions.C_PREPROCESSOR), + new TypedRegion(29, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + // replace one backslash with a newline + fDocument.replace(3, 1, "\n"); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 29, ICPartitions.C_PREPROCESSOR), + new TypedRegion(29, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + // insert backslash and newline inside multiline comment + fDocument.replace(26, 0, "\\\r\n"); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 32, ICPartitions.C_PREPROCESSOR), + new TypedRegion(32, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + // delete NL leaving only CR + fDocument.replace(28, 1, ""); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 31, ICPartitions.C_PREPROCESSOR), + new TypedRegion(31, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + // delete backslash + fDocument.replace(26, 1, ""); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 30, ICPartitions.C_PREPROCESSOR), + new TypedRegion(30, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + // insert white space before # + fDocument.replace(0, 0, " \t"); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 33, ICPartitions.C_PREPROCESSOR), + new TypedRegion(33, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); } catch (BadLocationException x) { assertTrue(false); diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/PartitionTokenScannerTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/PartitionTokenScannerTest.java index 090aad67131..50823de0a7a 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/PartitionTokenScannerTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/PartitionTokenScannerTest.java @@ -19,7 +19,6 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; -import org.eclipse.cdt.internal.ui.text.CPartitionScanner; import org.eclipse.cdt.internal.ui.text.FastCPartitionScanner; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; @@ -42,10 +41,10 @@ public class PartitionTokenScannerTest extends TestCase { protected void setUp() { fReference= new CPartitionScanner(); - fTestee= new FastCPartitionScanner(); + fTestee= new FastCPartitionScanner(true); } - // read sample java file + // read sample C file private IDocument getDocument(String name, String lineDelimiter) { try { InputStream stream= getClass().getResourceAsStream(name); diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java index d7889628654..8fa1f0c84e8 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java @@ -27,7 +27,7 @@ import org.eclipse.cdt.internal.ui.editor.SemanticHighlightings; */ public class SemanticHighlightingTest extends AbstractSemanticHighlightingTest { - private static final boolean PRINT_POSITIONS= true; + private static final boolean PRINT_POSITIONS= false; private static final Class THIS= SemanticHighlightingTest.class; diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java index a2f3fdb687f..0e74416f9a5 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java @@ -22,7 +22,7 @@ public class TextTestSuite extends TestSuite { public TextTestSuite() { super("Tests in package org.eclipse.cdt.ui.tests.text"); - //addTest(PartitionTokenScannerTest.suite()); + addTest(PartitionTokenScannerTest.suite()); addTest(NumberRuleTest.suite()); addTest(CAutoIndentTest.suite()); addTest(CPartitionerTest.suite()); diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index 96b38b7e9cc..61125322b44 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -576,7 +576,7 @@ name="%ColoringPreferencePage.name" category="org.eclipse.cdt.ui.preferences.CEditorPreferencePage" class="org.eclipse.cdt.internal.ui.preferences.CEditorColoringPreferencePage" - id="org.eclipse.cdt.ui.preferences.CEditorColoringPreferencePage"/> + id="org.eclipse.cdt.ui.preferences.CodeColoringPreferencePage"/> + * Performance optimization: since we know at this place + * that none of the clients expects the given range to be + * untouched we reuse the given range as return value. + *

+ */ + protected StyleRange modelStyleRange2WidgetStyleRange(StyleRange range) { + IRegion region= modelRange2WidgetRange(new Region(range.start, range.length)); + if (region != null) { + // don't clone the style range, but simply reuse it. + range.start= region.getOffset(); + range.length= region.getLength(); + return range; + } + return null; + } + } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmPreprocessorScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmPreprocessorScanner.java new file mode 100644 index 00000000000..775cb5c9a49 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmPreprocessorScanner.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * 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.internal.ui.editor.asm; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; + +import org.eclipse.cdt.core.parser.KeywordSetKey; +import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.cdt.core.parser.ParserLanguage; + +import org.eclipse.cdt.internal.ui.text.AbstractCScanner; +import org.eclipse.cdt.internal.ui.text.CHeaderRule; +import org.eclipse.cdt.internal.ui.text.ICColorConstants; +import org.eclipse.cdt.internal.ui.text.PreprocessorRule; +import org.eclipse.cdt.internal.ui.text.util.CColorManager; +import org.eclipse.cdt.internal.ui.text.util.CWhitespaceDetector; +import org.eclipse.cdt.internal.ui.text.util.CWordDetector; + +/** + * A preprocessor directive scanner for Asm source. + * + * @since 4.0 + */ +public class AsmPreprocessorScanner extends AbstractCScanner { + + /** Properties for tokens. */ + private static String[] fgTokenProperties= { + ICColorConstants.C_SINGLE_LINE_COMMENT, + ICColorConstants.C_MULTI_LINE_COMMENT, + ICColorConstants.PP_DIRECTIVE, + ICColorConstants.C_STRING, + ICColorConstants.PP_HEADER, + ICColorConstants.PP_DEFAULT, + }; + + /** + * Create a preprocessor directive scanner. + * + * @param colorManager + * @param store + */ + public AsmPreprocessorScanner(CColorManager colorManager, IPreferenceStore store) { + super(colorManager, store); + initialize(); + } + + /* + * @see org.eclipse.cdt.internal.ui.text.AbstractCScanner#createRules() + */ + protected List createRules() { + + Token defaultToken= getToken(ICColorConstants.PP_DEFAULT); + + List rules= new ArrayList(); + Token token; + + // Add generic white space rule. + rules.add(new WhitespaceRule(new CWhitespaceDetector())); + + token= getToken(ICColorConstants.PP_DIRECTIVE); + PreprocessorRule preprocessorRule = new PreprocessorRule(new CWordDetector(), defaultToken, getToken(ICColorConstants.C_SINGLE_LINE_COMMENT)); + Iterator iter; + iter = ParserFactory.getKeywordSet( KeywordSetKey.PP_DIRECTIVE, ParserLanguage.C ).iterator(); + while( iter.hasNext() ) { + String ppKeyword= (String) iter.next(); + if (ppKeyword.length() > 1) { + preprocessorRule.addWord(ppKeyword, token); + } + } + // add ## operator + preprocessorRule.addWord("##", token); //$NON-NLS-1$ + rules.add(preprocessorRule); + + token = getToken(ICColorConstants.PP_HEADER); + CHeaderRule headerRule = new CHeaderRule(token); + rules.add(headerRule); + + token = getToken(ICColorConstants.C_SINGLE_LINE_COMMENT); + IRule lineCommentRule = new EndOfLineRule("//", token, '\\', true); //$NON-NLS-1$ + rules.add(lineCommentRule); + lineCommentRule = new EndOfLineRule("#", token); //$NON-NLS-1$ + rules.add(lineCommentRule); + + token = getToken(ICColorConstants.C_MULTI_LINE_COMMENT); + IRule blockCommentRule = new MultiLineRule("/*", "*/", token, '\\'); //$NON-NLS-1$ //$NON-NLS-2$ + rules.add(blockCommentRule); + + setDefaultReturnToken(defaultToken); + return rules; + } + + /* + * @see org.eclipse.cdt.internal.ui.text.AbstractCScanner#getTokenProperties() + */ + protected String[] getTokenProperties() { + return fgTokenProperties; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmSourceViewerConfiguration.java index 96252ea8385..82c4f209b1e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmSourceViewerConfiguration.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmSourceViewerConfiguration.java @@ -22,6 +22,8 @@ import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; import org.eclipse.cdt.ui.text.ICPartitions; +import org.eclipse.cdt.internal.ui.text.PartitionDamager; + public class AsmSourceViewerConfiguration extends TextSourceViewerConfiguration { @@ -62,7 +64,15 @@ public class AsmSourceViewerConfiguration extends TextSourceViewerConfiguration return fAsmTextTools.getStringScanner(); } - + /** + * Returns the ASM preprocessor scanner for this configuration. + * + * @return the ASM preprocessor scanner + */ + protected RuleBasedScanner getPreprocessorScanner() { + return fAsmTextTools.getPreprocessorScanner(); + } + /* * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getConfiguredDocumentPartitioning(org.eclipse.jface.text.source.ISourceViewer) */ @@ -98,6 +108,10 @@ public class AsmSourceViewerConfiguration extends TextSourceViewerConfiguration reconciler.setDamager(dr, ICPartitions.C_CHARACTER); reconciler.setRepairer(dr, ICPartitions.C_CHARACTER); + dr= new DefaultDamagerRepairer(getPreprocessorScanner()); + reconciler.setDamager(new PartitionDamager(), ICPartitions.C_PREPROCESSOR); + reconciler.setRepairer(dr, ICPartitions.C_PREPROCESSOR); + reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); return reconciler; } @@ -111,7 +125,8 @@ public class AsmSourceViewerConfiguration extends TextSourceViewerConfiguration ICPartitions.C_MULTI_LINE_COMMENT, ICPartitions.C_SINGLE_LINE_COMMENT, ICPartitions.C_STRING, - ICPartitions.C_CHARACTER }; + ICPartitions.C_CHARACTER, + ICPartitions.C_PREPROCESSOR}; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java index 0f0c2e9b20e..ef0a8fee656 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java @@ -51,7 +51,8 @@ public class AsmTextTools { private CCommentScanner fSinglelineCommentScanner; /** The ASM string scanner */ private SingleTokenCScanner fStringScanner; - + /** The ASM preprocessor scanner */ + private AsmPreprocessorScanner fPreprocessorScanner; /** The preference store */ private IPreferenceStore fPreferenceStore; @@ -80,7 +81,8 @@ public class AsmTextTools { fColorManager= new CColorManager(); fCodeScanner= new AsmCodeScanner(fColorManager, store); - + fPreprocessorScanner= new AsmPreprocessorScanner(fColorManager, store); + fMultilineCommentScanner= new CCommentScanner(fColorManager, store, coreStore, ICColorConstants.C_MULTI_LINE_COMMENT); fSinglelineCommentScanner= new CCommentScanner(fColorManager, store, coreStore, ICColorConstants.C_SINGLE_LINE_COMMENT); fStringScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_STRING); @@ -145,33 +147,41 @@ public class AsmTextTools { } /** - * Returns a scanner which is configured to scan Java multiline comments. + * Returns a scanner which is configured to scan multiline comments. * - * @return a Java multiline comment scanner + * @return a multiline comment scanner */ public RuleBasedScanner getMultilineCommentScanner() { return fMultilineCommentScanner; } /** - * Returns a scanner which is configured to scan Java singleline comments. + * Returns a scanner which is configured to scan singleline comments. * - * @return a Java singleline comment scanner + * @return a singleline comment scanner */ public RuleBasedScanner getSinglelineCommentScanner() { return fSinglelineCommentScanner; } /** - * Returns a scanner which is configured to scan Java strings. + * Returns a scanner which is configured to scan strings. * - * @return a Java string scanner + * @return a string scanner */ public RuleBasedScanner getStringScanner() { return fStringScanner; } - + /** + * Returns a scanner which is configured to scan Asm preprocessor directives. + * + * @return an Asm preprocessor directives scanner + */ + public RuleBasedScanner getPreprocessorScanner() { + return fPreprocessorScanner; + } + /** * Determines whether the preference change encoded by the given event * changes the behavior of one its contained components. @@ -183,7 +193,8 @@ public class AsmTextTools { return fCodeScanner.affectsBehavior(event) || fMultilineCommentScanner.affectsBehavior(event) || fSinglelineCommentScanner.affectsBehavior(event) || - fStringScanner.affectsBehavior(event); + fStringScanner.affectsBehavior(event) || + fPreprocessorScanner.affectsBehavior(event); } /** @@ -201,6 +212,8 @@ public class AsmTextTools { fSinglelineCommentScanner.adaptToPreferenceChange(event); if (fStringScanner.affectsBehavior(event)) fStringScanner.adaptToPreferenceChange(event); + if (fPreprocessorScanner.affectsBehavior(event)) + fPreprocessorScanner.adaptToPreferenceChange(event); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorColoringConfigurationBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorColoringConfigurationBlock.java index 9bae89108cb..9f95b8201db 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorColoringConfigurationBlock.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorColoringConfigurationBlock.java @@ -210,7 +210,7 @@ class CEditorColoringConfigurationBlock extends AbstractConfigurationBlock { * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ public Object[] getElements(Object inputElement) { - return new String[] {fCodeCategory, fCommentsCategory}; + return new String[] {fCodeCategory, fCommentsCategory, fPreprocessorCategory}; } /* @@ -229,9 +229,11 @@ class CEditorColoringConfigurationBlock extends AbstractConfigurationBlock { if (parentElement instanceof String) { String entry= (String) parentElement; if (fCodeCategory.equals(entry)) - return fListModel.subList(3, fListModel.size()).toArray(); + return fListModel.subList(6, fListModel.size()).toArray(); if (fCommentsCategory.equals(entry)) return fListModel.subList(0, 3).toArray(); + if (fPreprocessorCategory.equals(entry)) + return fListModel.subList(3, 6).toArray(); } return new Object[0]; } @@ -240,8 +242,10 @@ class CEditorColoringConfigurationBlock extends AbstractConfigurationBlock { if (element instanceof String) return null; int index= fListModel.indexOf(element); - if (index >= 3) + if (index >= 6) return fCodeCategory; + if (index >= 3) + return fPreprocessorCategory; return fCommentsCategory; } @@ -274,6 +278,9 @@ class CEditorColoringConfigurationBlock extends AbstractConfigurationBlock { { PreferencesMessages.CEditorColoringConfigurationBlock_MultiLine, PreferenceConstants.EDITOR_MULTI_LINE_COMMENT_COLOR }, { PreferencesMessages.CEditorColoringConfigurationBlock_singleLine, PreferenceConstants.EDITOR_SINGLE_LINE_COMMENT_COLOR }, { PreferencesMessages.CEditorColoringConfigurationBlock_cCommentTaskTags, PreferenceConstants.EDITOR_TASK_TAG_COLOR }, + { PreferencesMessages.CEditorColoringConfigurationBlock_ppDirectives, PreferenceConstants.EDITOR_PP_DIRECTIVE_COLOR }, + { PreferencesMessages.CEditorColoringConfigurationBlock_ppOthers, PreferenceConstants.EDITOR_PP_DEFAULT_COLOR }, + { PreferencesMessages.CEditorColoringConfigurationBlock_ppHeaders, PreferenceConstants.EDITOR_PP_HEADER_COLOR }, { PreferencesMessages.CEditorColoringConfigurationBlock_keywords, PreferenceConstants.EDITOR_C_KEYWORD_COLOR }, // { PreferencesMessages.CEditorColoringConfigurationBlock_returnKeyword, PreferenceConstants.EDITOR_C_KEYWORD_RETURN_COLOR }, { PreferencesMessages.CEditorColoringConfigurationBlock_builtInTypes, PreferenceConstants.EDITOR_C_BUILTIN_TYPE_COLOR }, @@ -281,12 +288,12 @@ class CEditorColoringConfigurationBlock extends AbstractConfigurationBlock { { PreferencesMessages.CEditorColoringConfigurationBlock_strings, PreferenceConstants.EDITOR_C_STRING_COLOR }, { PreferencesMessages.CEditorColoringConfigurationBlock_braces, PreferenceConstants.EDITOR_C_BRACES_COLOR }, { PreferencesMessages.CEditorColoringConfigurationBlock_numbers, PreferenceConstants.EDITOR_C_NUMBER_COLOR }, - { PreferencesMessages.CEditorColoringConfigurationBlock_headers, PreferenceConstants.EDITOR_C_HEADER_COLOR }, { PreferencesMessages.CEditorColoringConfigurationBlock_others, PreferenceConstants.EDITOR_C_DEFAULT_COLOR }, }; private final String fCodeCategory= PreferencesMessages.CEditorColoringConfigurationBlock_coloring_category_code; private final String fCommentsCategory= PreferencesMessages.CEditorColoringConfigurationBlock_coloring_category_comments; + private final String fPreprocessorCategory= PreferencesMessages.CEditorColoringConfigurationBlock_coloring_category_preprocessor; private ColorSelector fSyntaxForegroundColorEditor; private Label fColorEditorLabel; @@ -560,6 +567,8 @@ class CEditorColoringConfigurationBlock extends AbstractConfigurationBlock { return 0; if (fCommentsCategory.equals(element)) return 2; + if (fPreprocessorCategory.equals(element)) + return 3; // to sort semantic settings after partition based ones: // if (element instanceof SemanticHighlightingColorListItem) // return 1; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java index 46d00a76dfa..583b2a533b4 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.preferences; @@ -88,11 +89,14 @@ public final class PreferencesMessages extends NLS { public static String CEditorColoringConfigurationBlock_operators; public static String CEditorColoringConfigurationBlock_braces; public static String CEditorColoringConfigurationBlock_numbers; - public static String CEditorColoringConfigurationBlock_headers; public static String CEditorColoringConfigurationBlock_others; + public static String CEditorColoringConfigurationBlock_ppDirectives; + public static String CEditorColoringConfigurationBlock_ppOthers; + public static String CEditorColoringConfigurationBlock_ppHeaders; public static String CEditorColoringConfigurationBlock_cCommentTaskTags; public static String CEditorColoringConfigurationBlock_coloring_category_code; public static String CEditorColoringConfigurationBlock_coloring_category_comments; + public static String CEditorColoringConfigurationBlock_coloring_category_preprocessor; public static String CEditorColoringConfigurationBlock_coloring_element; public static String CEditorColoringConfigurationBlock_link; public static String CEditorColoringConfigurationBlock_enable; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties index aacfc2cd4f4..de6c460c68e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties @@ -7,6 +7,7 @@ # # Contributors: # IBM Corporation - initial API and implementation +# Anton Leherbauer (Wind River Systems) ############################################################################### OptionsConfigurationBlock_builderror_title=Preference Changes @@ -90,11 +91,14 @@ CEditorColoringConfigurationBlock_strings=Strings CEditorColoringConfigurationBlock_operators=Operators CEditorColoringConfigurationBlock_braces=Braces CEditorColoringConfigurationBlock_numbers=Numbers -CEditorColoringConfigurationBlock_headers=Headers CEditorColoringConfigurationBlock_others=Others +CEditorColoringConfigurationBlock_ppDirectives=Directives +CEditorColoringConfigurationBlock_ppHeaders=Headers +CEditorColoringConfigurationBlock_ppOthers=Others CEditorColoringConfigurationBlock_cCommentTaskTags=Task Tags CEditorColoringConfigurationBlock_coloring_category_code=Code CEditorColoringConfigurationBlock_coloring_category_comments=Comments +CEditorColoringConfigurationBlock_coloring_category_preprocessor=Preprocessor CEditorColoringConfigurationBlock_coloring_element=Element: # DO NOT TRANSLATE "org.eclipse.ui.preferencePages.GeneralTextEditor" and "org.eclipse.ui.preferencePages.ColorsAndFonts" CEditorColoringConfigurationBlock_link=Default colors and font can be configured on the Text Editors and on the Colors and Fonts preference page. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java index d79287e9c39..7a01b06ce2a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java @@ -19,6 +19,7 @@ import java.util.List; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.rules.IRule; import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; import org.eclipse.jface.text.rules.WordRule; import org.eclipse.jface.util.PropertyChangeEvent; @@ -26,6 +27,7 @@ import org.eclipse.cdt.core.parser.KeywordSetKey; import org.eclipse.cdt.core.parser.ParserFactory; import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.internal.ui.text.util.CWhitespaceDetector; import org.eclipse.cdt.internal.ui.text.util.CWordDetector; @@ -43,11 +45,9 @@ public final class CCodeScanner extends AbstractCScanner { private static String[] fgTokenProperties= { ICColorConstants.C_KEYWORD, ICColorConstants.C_TYPE, - ICColorConstants.C_STRING, ICColorConstants.C_OPERATOR, ICColorConstants.C_BRACES, ICColorConstants.C_NUMBER, - ICColorConstants.C_HEADER, ICColorConstants.C_DEFAULT, }; @@ -78,7 +78,7 @@ public final class CCodeScanner extends AbstractCScanner { Token token; // Add generic white space rule. - //rules.add(new WhitespaceRule(new CWhitespaceDetector())); + rules.add(new WhitespaceRule(new CWhitespaceDetector())); // Add word rule for keywords, types, and constants. token= getToken(ICColorConstants.C_DEFAULT); @@ -102,10 +102,6 @@ public final class CCodeScanner extends AbstractCScanner { NumberRule numberRule = new NumberRule(token); rules.add(numberRule); - token = getToken(ICColorConstants.C_HEADER); - CHeaderRule headerRule = new CHeaderRule(token); - rules.add(headerRule); - token = getToken(ICColorConstants.C_OPERATOR); COperatorRule opRule = new COperatorRule(token); rules.add(opRule); @@ -114,15 +110,6 @@ public final class CCodeScanner extends AbstractCScanner { CBraceRule braceRule = new CBraceRule(token); rules.add(braceRule); - token = getToken(ICColorConstants.C_TYPE); - PreprocessorRule preprocessorRule = new PreprocessorRule(new CWordDetector(), token); - - i = ParserFactory.getKeywordSet( KeywordSetKey.PP_DIRECTIVE, ParserLanguage.C ).iterator(); - while( i.hasNext() ) - preprocessorRule.addWord((String) i.next(), token); - - rules.add(preprocessorRule); - setDefaultReturnToken(getToken(ICColorConstants.C_DEFAULT)); return rules; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeaderRule.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeaderRule.java index 105bcb04d7b..f2729a4bd8b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeaderRule.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeaderRule.java @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Markus Schorn (Wind River Systems) + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.text; @@ -43,11 +44,12 @@ public class CHeaderRule implements IRule { int lookAhead = 1; int contentLength = 0; - if (current == '<') { + if (current == '<' || current == '"') { + int expected = current == '<' ? '>' : current; do { current = scanner.read(); lookAhead++; - if (current == '>') { + if (current == expected) { if (contentLength < 1) { break; } @@ -113,8 +115,8 @@ public class CHeaderRule implements IRule { lookBehind++; } while (Character.isWhitespace((char) current)); scanner.read(); - - if (searchBackwards(scanner, "#include")) { //$NON-NLS-1$ + --lookBehind; + if (searchBackwards(scanner, "include")) { //$NON-NLS-1$ result = true; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPreprocessorScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPreprocessorScanner.java new file mode 100644 index 00000000000..85ef9df2f35 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPreprocessorScanner.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * 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.internal.ui.text; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.PatternRule; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; +import org.eclipse.jface.text.rules.WordRule; + +import org.eclipse.cdt.core.parser.KeywordSetKey; +import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.cdt.core.parser.ParserLanguage; + +import org.eclipse.cdt.internal.ui.text.util.CWhitespaceDetector; +import org.eclipse.cdt.internal.ui.text.util.CWordDetector; + +/** + * A scanner for preprocessor directives. + * + * @since 4.0 + */ +public class CPreprocessorScanner extends AbstractCScanner { + + /** Properties for tokens. */ + private static String[] fgTokenProperties= { + ICColorConstants.C_SINGLE_LINE_COMMENT, + ICColorConstants.C_MULTI_LINE_COMMENT, + ICColorConstants.C_KEYWORD, + ICColorConstants.PP_DIRECTIVE, + ICColorConstants.PP_DEFAULT, + ICColorConstants.C_TYPE, + ICColorConstants.C_STRING, + ICColorConstants.PP_HEADER + }; + + private boolean fIsCpp; + + /** + * Creates a C/C++ preprocessor scanner. + * + * @param manager the color manager. + * @param store the preference store. + * @param isCpp if true C++ keywords are used, else C keywords + */ + public CPreprocessorScanner(IColorManager manager, IPreferenceStore store, boolean isCpp) { + super(manager, store); + fIsCpp= isCpp; + initialize(); + } + + /* + * @see org.eclipse.cdt.internal.ui.text.AbstractCScanner#createRules() + */ + protected List createRules() { + + Token defaultToken= getToken(ICColorConstants.PP_DEFAULT); + + List rules= new ArrayList(); + Token token; + + // Add generic white space rule. + rules.add(new WhitespaceRule(new CWhitespaceDetector())); + + token= getToken(ICColorConstants.PP_DIRECTIVE); + PreprocessorRule preprocessorRule = new PreprocessorRule(new CWordDetector(), token); + Iterator iter; + if (fIsCpp) { + iter = ParserFactory.getKeywordSet( KeywordSetKey.PP_DIRECTIVE, ParserLanguage.CPP ).iterator(); + } else { + iter = ParserFactory.getKeywordSet( KeywordSetKey.PP_DIRECTIVE, ParserLanguage.C ).iterator(); + } + while( iter.hasNext() ) + preprocessorRule.addWord((String) iter.next(), token); + + // add ## operator + preprocessorRule.addWord("##", token); //$NON-NLS-1$ + rules.add(preprocessorRule); + + // Add word rule for keywords, types, and constants. + WordRule wordRule= new WordRule(new CWordDetector(), defaultToken); + + token= getToken(ICColorConstants.C_KEYWORD); + if (fIsCpp) { + iter = ParserFactory.getKeywordSet( KeywordSetKey.KEYWORDS, ParserLanguage.CPP ).iterator(); + } else { + iter = ParserFactory.getKeywordSet( KeywordSetKey.KEYWORDS, ParserLanguage.C ).iterator(); + } + while( iter.hasNext() ) + wordRule.addWord((String) iter.next(), token); + + token= getToken(ICColorConstants.C_TYPE); + iter = ParserFactory.getKeywordSet( KeywordSetKey.TYPES, ParserLanguage.C ).iterator(); + while( iter.hasNext() ) + wordRule.addWord((String) iter.next(), token); + rules.add(wordRule); + + token = getToken(ICColorConstants.PP_HEADER); + CHeaderRule headerRule = new CHeaderRule(token); + rules.add(headerRule); + + token = getToken(ICColorConstants.C_SINGLE_LINE_COMMENT); + IRule lineCommentRule = new EndOfLineRule("//", token, '\\', true); //$NON-NLS-1$ + rules.add(lineCommentRule); + + token = getToken(ICColorConstants.C_MULTI_LINE_COMMENT); + IRule blockCommentRule = new MultiLineRule("/*", "*/", token, '\\'); //$NON-NLS-1$ //$NON-NLS-2$ + rules.add(blockCommentRule); + + token = getToken(ICColorConstants.C_STRING); + IRule stringRule = new PatternRule("\"", "\"", token, '\\', true, true, true); //$NON-NLS-1$ //$NON-NLS-2$ + rules.add(stringRule); + + token = getToken(ICColorConstants.C_STRING); + IRule charRule = new PatternRule("'", "'", token, '\\', true, true, true); //$NON-NLS-1$ //$NON-NLS-2$ + rules.add(charRule); + + setDefaultReturnToken(defaultToken); + return rules; + } + + /* + * @see org.eclipse.cdt.internal.ui.text.AbstractCScanner#getTokenProperties() + */ + protected String[] getTokenProperties() { + return fgTokenProperties; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java index aa4d425b94b..609340a7276 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java @@ -118,6 +118,24 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { return fTextTools.getStringScanner(); } + /** + * Returns the C preprocessor scanner for this configuration. + * + * @return the C preprocessor scanner + */ + protected RuleBasedScanner getCPreprocessorScanner() { + return fTextTools.getCPreprocessorScanner(); + } + + /** + * Returns the C++ preprocessor scanner for this configuration. + * + * @return the C++ preprocessor scanner + */ + protected RuleBasedScanner getCppPreprocessorScanner() { + return fTextTools.getCppPreprocessorScanner(); + } + /** * Returns the color manager for this configuration. * @@ -153,6 +171,7 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { presenter.setInformationProvider(provider, ICPartitions.C_SINGLE_LINE_COMMENT); presenter.setInformationProvider(provider, ICPartitions.C_STRING); presenter.setInformationProvider(provider, ICPartitions.C_CHARACTER); + presenter.setInformationProvider(provider, ICPartitions.C_PREPROCESSOR); presenter.setSizeConstraints(20, 20, true, false); presenter.setRestoreInformationControlBounds(getSettings("outline_presenter_bounds"), true, true); //$NON-NLS-1$ return presenter; @@ -167,8 +186,9 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); RuleBasedScanner scanner = null; + ILanguage language= null; if(sourceViewer instanceof CSourceViewer) { - ILanguage language = ((CSourceViewer)sourceViewer).getLanguage(); + language = ((CSourceViewer)sourceViewer).getLanguage(); if (language instanceof GPPLanguage) { scanner = fTextTools.getCppCodeScanner(); } else if (language instanceof GCCLanguage) { @@ -206,6 +226,18 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { reconciler.setDamager(dr, ICPartitions.C_CHARACTER); reconciler.setRepairer(dr, ICPartitions.C_CHARACTER); + if (language instanceof GPPLanguage) { + dr= new DefaultDamagerRepairer(getCppPreprocessorScanner()); + } else if (language instanceof GCCLanguage) { + dr= new DefaultDamagerRepairer(getCPreprocessorScanner()); + } else { + dr= null; + } + if (dr != null) { + reconciler.setDamager(new PartitionDamager(), ICPartitions.C_PREPROCESSOR); + reconciler.setRepairer(dr, ICPartitions.C_PREPROCESSOR); + } + return reconciler; } @@ -400,7 +432,8 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { ICPartitions.C_MULTI_LINE_COMMENT, ICPartitions.C_SINGLE_LINE_COMMENT, ICPartitions.C_STRING, - ICPartitions.C_CHARACTER}; + ICPartitions.C_CHARACTER, + ICPartitions.C_PREPROCESSOR}; } /** diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java index f6baedc107f..b9f6c44333c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * QNX Software System + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.text; @@ -51,12 +52,16 @@ public class CTextTools { private CppCodeScanner fCppCodeScanner; /** The C partitions scanner */ private FastCPartitionScanner fPartitionScanner; - /** The Java multiline comment scanner */ + /** The C multiline comment scanner */ private CCommentScanner fMultilineCommentScanner; - /** The Java singleline comment scanner */ + /** The C singleline comment scanner */ private CCommentScanner fSinglelineCommentScanner; - /** The Java string scanner */ + /** The C string scanner */ private SingleTokenCScanner fStringScanner; + /** The C preprocessor scanner */ + private CPreprocessorScanner fCPreprocessorScanner; + /** The C++ preprocessor scanner */ + private CPreprocessorScanner fCppPreprocessorScanner; /** The preference store */ private IPreferenceStore fPreferenceStore; @@ -99,6 +104,8 @@ public class CTextTools { fMultilineCommentScanner= new CCommentScanner(fColorManager, store, coreStore, ICColorConstants.C_MULTI_LINE_COMMENT); fSinglelineCommentScanner= new CCommentScanner(fColorManager, store, coreStore, ICColorConstants.C_SINGLE_LINE_COMMENT); fStringScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_STRING); + fCPreprocessorScanner= new CPreprocessorScanner(fColorManager, store, false); + fCppPreprocessorScanner= new CPreprocessorScanner(fColorManager, store, true); fPreferenceStore = store; fPreferenceStore.addPropertyChangeListener(fPreferenceListener); @@ -190,7 +197,8 @@ public class CTextTools { ICPartitions.C_MULTI_LINE_COMMENT, ICPartitions.C_SINGLE_LINE_COMMENT, ICPartitions.C_STRING, - ICPartitions.C_CHARACTER + ICPartitions.C_CHARACTER, + ICPartitions.C_PREPROCESSOR }; return new FastPartitioner(getPartitionScanner(), types); @@ -215,14 +223,31 @@ public class CTextTools { } /** - * Returns a scanner which is configured to scan Java strings. + * Returns a scanner which is configured to scan C strings. * - * @return a Java string scanner + * @return a C string scanner */ public RuleBasedScanner getStringScanner() { return fStringScanner; } + /** + * Returns a scanner which is configured to scan C preprocessor directives. + * + * @return a C preprocessor directives scanner + */ + public RuleBasedScanner getCPreprocessorScanner() { + return fCPreprocessorScanner; + } + + /** + * Returns a scanner which is configured to scan C++ preprocessor directives. + * + * @return a C++ preprocessor directives scanner + */ + public RuleBasedScanner getCppPreprocessorScanner() { + return fCppPreprocessorScanner; + } /** * Determines whether the preference change encoded by the given event @@ -236,7 +261,8 @@ public class CTextTools { fCppCodeScanner.affectsBehavior(event) || fMultilineCommentScanner.affectsBehavior(event) || fSinglelineCommentScanner.affectsBehavior(event) || - fStringScanner.affectsBehavior(event); + fStringScanner.affectsBehavior(event) || + fCPreprocessorScanner.affectsBehavior(event); } /** @@ -256,6 +282,10 @@ public class CTextTools { fSinglelineCommentScanner.adaptToPreferenceChange(event); if (fStringScanner.affectsBehavior(event)) fStringScanner.adaptToPreferenceChange(event); + if (fCPreprocessorScanner.affectsBehavior(event)) { + fCPreprocessorScanner.adaptToPreferenceChange(event); + fCppPreprocessorScanner.adaptToPreferenceChange(event); + } } /** diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java index 3d0b38a0842..5c153bbd80e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java @@ -19,6 +19,7 @@ import java.util.List; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.rules.IRule; import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; import org.eclipse.jface.text.rules.WordRule; import org.eclipse.jface.util.PropertyChangeEvent; @@ -26,6 +27,7 @@ import org.eclipse.cdt.core.parser.KeywordSetKey; import org.eclipse.cdt.core.parser.ParserFactory; import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.internal.ui.text.util.CWhitespaceDetector; import org.eclipse.cdt.internal.ui.text.util.CWordDetector; @@ -41,11 +43,9 @@ public final class CppCodeScanner extends AbstractCScanner { private static String[] fgTokenProperties= { ICColorConstants.C_KEYWORD, ICColorConstants.C_TYPE, - ICColorConstants.C_STRING, ICColorConstants.C_OPERATOR, ICColorConstants.C_BRACES, ICColorConstants.C_NUMBER, - ICColorConstants.C_HEADER, ICColorConstants.C_DEFAULT }; @@ -74,9 +74,8 @@ public final class CppCodeScanner extends AbstractCScanner { Token token; // Add generic whitespace rule. - //rules.add(new WhitespaceRule(new CWhitespaceDetector())); + rules.add(new WhitespaceRule(new CWhitespaceDetector())); - // Add word rule for keywords, types, and constants. token= getToken(ICColorConstants.C_DEFAULT); WordRule wordRule= new WordRule(new CWordDetector(), token); @@ -93,23 +92,10 @@ public final class CppCodeScanner extends AbstractCScanner { wordRule.addWord(fgConstants[i], token); rules.add(wordRule); - token = getToken(ICColorConstants.C_TYPE); - PreprocessorRule preprocessorRule = new PreprocessorRule(new CWordDetector(), token); - iter = ParserFactory.getKeywordSet( KeywordSetKey.PP_DIRECTIVE, ParserLanguage.CPP ).iterator(); - - while( iter.hasNext() ) - preprocessorRule.addWord((String) iter.next(), token); - - rules.add(preprocessorRule); - token = getToken(ICColorConstants.C_NUMBER); NumberRule numberRule = new NumberRule(token); rules.add(numberRule); - token = getToken(ICColorConstants.C_HEADER); - CHeaderRule headerRule = new CHeaderRule(token); - rules.add(headerRule); - token = getToken(ICColorConstants.C_OPERATOR); COperatorRule opRule = new COperatorRule(token); rules.add(opRule); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/FastCPartitionScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/FastCPartitionScanner.java index 3dcb2932b6a..f9bc09de982 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/FastCPartitionScanner.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/FastCPartitionScanner.java @@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.ui.text; +import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.rules.ICharacterScanner; import org.eclipse.jface.text.rules.IPartitionTokenScanner; @@ -24,9 +25,9 @@ import org.eclipse.cdt.ui.text.ICPartitions; /** * This scanner recognizes the C multi line comments, C single line comments, - * C strings and C characters. + * C strings, C characters and C preprocessor directives. */ -public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitions { +public final class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitions { // states private static final int CCODE= 0; @@ -34,17 +35,19 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio private static final int MULTI_LINE_COMMENT= 2; private static final int CHARACTER= 3; private static final int STRING= 4; + private static final int PREPROCESSOR= 5; + private static final int PREPROCESSOR_MULTI_LINE_COMMENT= 6; // beginning of prefixes and postfixes private static final int NONE= 0; - private static final int BACKSLASH= 1; // postfix for STRING and CHARACTER + private static final int BACKSLASH= 1; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT private static final int SLASH= 2; // prefix for SINGLE_LINE or MULTI_LINE private static final int SLASH_STAR= 3; // prefix for MULTI_LINE_COMMENT private static final int STAR= 4; // postfix for MULTI_LINE_COMMENT private static final int CARRIAGE_RETURN=5; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT + private static final int BACKSLASH_CR= 6; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT /** The scanner. */ -// private final BufferedRuleBasedScanner fScanner= new BufferedRuleBasedScanner(1000); private final BufferedDocumentScanner fScanner= new BufferedDocumentScanner(1000); // faster implementation /** The offset of the last returned token. */ @@ -58,62 +61,213 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio private int fLast; /** The amount of characters already read on first call to nextToken(). */ private int fPrefixLength; + /** Indicate whether current char is first non-whitespace char on the line*/ + private boolean fFirstCharOnLine= true; + + // emulate CPartitionScanner + private boolean fEmulate= false; + private int fCCodeOffset; + private int fCCodeLength; private final IToken[] fTokens= new IToken[] { new Token(null), new Token(C_SINGLE_LINE_COMMENT), new Token(C_MULTI_LINE_COMMENT), new Token(C_CHARACTER), - new Token(C_STRING) + new Token(C_STRING), + new Token(C_PREPROCESSOR), + new Token(C_PREPROCESSOR) }; + public FastCPartitionScanner(boolean emulate) { + fEmulate= emulate; + } + + public FastCPartitionScanner() { + this(false); + } + /* * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken() */ public IToken nextToken() { + + // emulate CPartitionScanner + if (fEmulate) { + if (fCCodeOffset != -1 && fTokenOffset + fTokenLength != fCCodeOffset + fCCodeLength) { + fTokenOffset += fTokenLength; + return fTokens[CCODE]; + } else { + fCCodeOffset= -1; + fCCodeLength= 0; + } + } + fTokenOffset += fTokenLength; fTokenLength= fPrefixLength; - final char[][] delimiters = fScanner.getLegalLineDelimiters(); - while (true) { final int ch= fScanner.read(); - - if (ch == ICharacterScanner.EOF) { + + final boolean isFirstCharOnLine= fFirstCharOnLine; + if (fFirstCharOnLine && ch != ' ' && ch != '\t') { + fFirstCharOnLine= false; + } + // characters + switch (ch) { + case ICharacterScanner.EOF: if (fTokenLength > 0) { fLast= NONE; // ignore last return preFix(fState, CCODE, NONE, 0); + } else { + fLast= NONE; + fPrefixLength= 0; + return Token.EOF; } - fLast= NONE; - fPrefixLength= 0; - return Token.EOF; - } - - // detect if we're at the end of the line - final int delim = detectLineDelimiter(ch, fScanner, delimiters); - if (delim != -1) { - final int len = delimiters[delim].length; - if (len > 1) { - // adjust the token length if the delimiter was 2 or more chars - fTokenLength += (len - 1); - } + + case '\r': + fFirstCharOnLine= true; + if (!fEmulate && fLast == BACKSLASH) { + fLast= BACKSLASH_CR; + fTokenLength++; + continue; + } else if (!fEmulate && fLast != CARRIAGE_RETURN) { + fLast= CARRIAGE_RETURN; + fTokenLength++; + continue; + } else { + // fEmulate || fLast == CARRIAGE_RETURN + switch (fState) { + case SINGLE_LINE_COMMENT: + case CHARACTER: + case STRING: + case PREPROCESSOR: + if (fTokenLength > 0) { + IToken token= fTokens[fState]; + + // emulate CPartitionScanner + if (fEmulate) { + fTokenLength++; + fLast= NONE; + fPrefixLength= 0; + } else { + fLast= CARRIAGE_RETURN; + fPrefixLength= 1; + } + + fState= CCODE; + return token; + + } else { + consume(); + continue; + } + + default: + consume(); + continue; + } + } + + case '\\': + if (fLast == BACKSLASH) { + consume(); + continue; + } + break; + + case '\n': + fFirstCharOnLine= true; switch (fState) { case SINGLE_LINE_COMMENT: case CHARACTER: case STRING: + case PREPROCESSOR: // assert(fTokenLength > 0); // if last char was a backslash then we have an escaped line - if (fLast != BACKSLASH) { + if (fLast != BACKSLASH && fLast != BACKSLASH_CR) { return postFix(fState); } - // FALLTHROUGH default: consume(); continue; } + default: + if (!fEmulate && fLast == CARRIAGE_RETURN) { + switch (fState) { + case SINGLE_LINE_COMMENT: + case CHARACTER: + case STRING: + + int last; + int newState; + switch (ch) { + case '/': + last= SLASH; + newState= CCODE; + break; + + case '*': + last= STAR; + newState= CCODE; + break; + + case '\'': + last= NONE; + newState= CHARACTER; + break; + + case '"': + last= NONE; + newState= STRING; + break; + + case '\r': + last= CARRIAGE_RETURN; + newState= CCODE; + break; + + case '\\': + last= BACKSLASH; + newState= CCODE; + break; + + default: + last= NONE; + newState= CCODE; + break; + } + + fLast= NONE; // ignore fLast + return preFix(fState, newState, last, 1); + + case CCODE: + if (ch == '#' && isFirstCharOnLine) { + fLast= NONE; // ignore fLast + int column= fScanner.getColumn() - 1; + fTokenLength -= column; + if (fTokenLength > 0) { + return preFix(fState, PREPROCESSOR, NONE, column + 1); + } else { + preFix(fState, PREPROCESSOR, NONE, column + 1); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + } + break; + + case PREPROCESSOR: + fLast= NONE; // ignore fLast + return preFix(fState, CCODE, NONE, 1); + + default: + break; + } + } } // states @@ -124,69 +278,143 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio if (fLast == SLASH) { if (fTokenLength - getLastLength(fLast) > 0) { return preFix(CCODE, SINGLE_LINE_COMMENT, NONE, 2); - } - preFix(CCODE, SINGLE_LINE_COMMENT, NONE, 2); - fTokenOffset += fTokenLength; - fTokenLength= fPrefixLength; - break; + } else { + preFix(CCODE, SINGLE_LINE_COMMENT, NONE, 2); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + } else { + fTokenLength++; + fLast= SLASH; + break; } - fTokenLength++; - fLast= SLASH; - break; case '*': if (fLast == SLASH) { - if (fTokenLength - getLastLength(fLast) > 0) + if (fTokenLength - getLastLength(fLast) > 0) { return preFix(CCODE, MULTI_LINE_COMMENT, SLASH_STAR, 2); - - preFix(CCODE, MULTI_LINE_COMMENT, SLASH_STAR, 2); - fTokenOffset += fTokenLength; - fTokenLength= fPrefixLength; - break; + } else { + preFix(CCODE, MULTI_LINE_COMMENT, SLASH_STAR, 2); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + } else { + consume(); + break; } - consume(); - break; case '\'': fLast= NONE; // ignore fLast if (fTokenLength > 0) { return preFix(CCODE, CHARACTER, NONE, 1); + } else { + preFix(CCODE, CHARACTER, NONE, 1); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; } - preFix(CCODE, CHARACTER, NONE, 1); - fTokenOffset += fTokenLength; - fTokenLength= fPrefixLength; - break; case '"': fLast= NONE; // ignore fLast if (fTokenLength > 0 ) { return preFix(CCODE, STRING, NONE, 1); + } else { + preFix(CCODE, STRING, NONE, 1); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; } - preFix(CCODE, STRING, NONE, 1); - fTokenOffset += fTokenLength; - fTokenLength= fPrefixLength; - break; - + + case '#': + if (!fEmulate && isFirstCharOnLine) { + int column= fScanner.getColumn() - 1; + fTokenLength -= column; + if (fTokenLength > 0) { + return preFix(fState, PREPROCESSOR, NONE, column + 1); + } else { + preFix(fState, PREPROCESSOR, NONE, column + 1); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + } + // fallthrough default: consume(); break; } break; - + case SINGLE_LINE_COMMENT: - switch (ch) { - case '\\': + switch (ch) { + case '\\': fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH; fTokenLength++; break; + + default: + consume(); + break; + } + break; + + case PREPROCESSOR: + switch (ch) { + case '\\': + fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH; + fTokenLength++; + break; + + case '/': + if (fLast == SLASH) { + consume(); + break; + } else { + fTokenLength++; + fLast= SLASH; + break; + } + + case '*': + if (fLast == SLASH) { + fState= PREPROCESSOR_MULTI_LINE_COMMENT; + consume(); + break; + } else { + consume(); + break; + } + + default: + consume(); + break; + } + break; + + case PREPROCESSOR_MULTI_LINE_COMMENT: + switch (ch) { + case '*': + fTokenLength++; + fLast= STAR; + break; + + case '/': + if (fLast == STAR) { + fState= PREPROCESSOR; + consume(); + } + break; + default: consume(); - break; + break; } break; - + case MULTI_LINE_COMMENT: switch (ch) { case '*': @@ -197,9 +425,10 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio case '/': if (fLast == STAR) { return postFix(MULTI_LINE_COMMENT); + } else { + consume(); + break; } - consume(); - break; default: consume(); @@ -218,9 +447,10 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio if (fLast != BACKSLASH) { return postFix(STRING); + } else { + consume(); + break; } - consume(); - break; default: consume(); @@ -239,9 +469,10 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio if (fLast != BACKSLASH) { return postFix(CHARACTER); + } else { + consume(); + break; } - consume(); - break; default: consume(); @@ -252,46 +483,6 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio } } - /** - * returns index of longest matching element in delimiters - */ - private static final int detectLineDelimiter(final int ch, final ICharacterScanner scanner, final char[][] delimiters) { - int longestDelimiter = -1; - int maxLen = 0; - for (int i = 0; i < delimiters.length; i++) { - final char[] delim = delimiters[i]; - if (ch == delim[0]) { - final int len = delim.length; - if (len > maxLen && (len == 1 || sequenceDetected(scanner, delim, 1, len))) { - maxLen = len; - longestDelimiter = i; - } - } - } - return longestDelimiter; - } - - /** - * true if sequence matches between beginIndex (inclusive) and endIndex (exclusive) - */ - private static final boolean sequenceDetected(final ICharacterScanner scanner, final char[] sequence, final int beginIndex, final int endIndex) { - int charsRead = 0; - for (int i = beginIndex; i < endIndex; ++i) { - final int c = scanner.read(); - if (c != ICharacterScanner.EOF) { - ++charsRead; - } - if (c != sequence[i]) { - // Non-matching character detected, rewind the scanner back to the start. - for (; charsRead > 0; --charsRead) { - scanner.unread(); - } - return false; - } - } - return true; - } - private static final int getLastLength(int last) { switch (last) { default: @@ -307,6 +498,7 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio return 1; case SLASH_STAR: + case BACKSLASH_CR: return 2; } @@ -326,12 +518,25 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio } private final IToken preFix(int state, int newState, int last, int prefixLength) { - fTokenLength -= getLastLength(fLast); - fLast= last; - fPrefixLength= prefixLength; - IToken token= fTokens[state]; - fState= newState; - return token; + // emulate CPartitionScanner + if (fEmulate && state == CCODE && (fTokenLength - getLastLength(fLast) > 0)) { + fTokenLength -= getLastLength(fLast); + fCCodeOffset= fTokenOffset; + fCCodeLength= fTokenLength; + fTokenLength= 1; + fState= newState; + fPrefixLength= prefixLength; + fLast= last; + return fTokens[state]; + + } else { + fTokenLength -= getLastLength(fLast); + fLast= last; + fPrefixLength= prefixLength; + IToken token= fTokens[state]; + fState= newState; + return token; + } } private static int getState(String contentType) { @@ -350,6 +555,9 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio else if (contentType.equals(C_CHARACTER)) return CHARACTER; + + else if (contentType.equals(C_PREPROCESSOR)) + return PREPROCESSOR; else return CCODE; @@ -373,6 +581,18 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio fState= getState(contentType); } + try { + int column= fScanner.getColumn(); + fFirstCharOnLine= column == 0 || document.get(offset-column, column).trim().length() == 0; + } catch (BadLocationException exc) { + fFirstCharOnLine= true; + } + + // emulate CPartitionScanner + if (fEmulate) { + fCCodeOffset= -1; + fCCodeLength= 0; + } } /* @@ -387,6 +607,18 @@ public class FastCPartitionScanner implements IPartitionTokenScanner, ICPartitio fLast= NONE; fState= CCODE; + try { + int column= fScanner.getColumn(); + fFirstCharOnLine= column == 0 || document.get(offset-column, column).trim().length() == 0; + } catch (BadLocationException exc) { + fFirstCharOnLine= true; + } + + // emulate CPartitionScanner + if (fEmulate) { + fCCodeOffset= -1; + fCCodeLength= 0; + } } /* diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICColorConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICColorConstants.java index 8f3466b1db2..7a6ec0768fa 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICColorConstants.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICColorConstants.java @@ -18,30 +18,32 @@ package org.eclipse.cdt.internal.ui.text; */ public interface ICColorConstants { - /* The prefix all color constants start with */ - String PREFIX= "c_"; //$NON-NLS-1$ - - /* The color key for multi-line comments in C code. */ + /** The color key for multi-line comments in C code. */ String C_MULTI_LINE_COMMENT= "c_multi_line_comment"; //$NON-NLS-1$ - /* The color key for single-line comments in C code. */ + /** The color key for single-line comments in C code. */ String C_SINGLE_LINE_COMMENT= "c_single_line_comment"; //$NON-NLS-1$ - /* The color key for keywords in C code. */ + /** The color key for keywords in C code. */ String C_KEYWORD= "c_keyword"; //$NON-NLS-1$ - /* The color key for builtin types in C code. */ + /** The color key for builtin types in C code. */ String C_TYPE= "c_type"; //$NON-NLS-1$ - /* The color key for string and character literals in C code. */ + /** The color key for string and character literals in C code. */ String C_STRING= "c_string"; //$NON-NLS-1$ /** The color key for operators. */ - String C_OPERATOR = "c_operators"; //$NON-NLS-1$ + String C_OPERATOR= "c_operators"; //$NON-NLS-1$ /** The color key for braces. */ - String C_BRACES = "c_braces"; //$NON-NLS-1$ + String C_BRACES= "c_braces"; //$NON-NLS-1$ /** The color key for numbers. */ - String C_NUMBER = "c_numbers"; //$NON-NLS-1$ - /** The color key for headers. */ - String C_HEADER = "c_header"; //$NON-NLS-1$ - /* The color key for everthing in C code for which no other color is specified. */ + String C_NUMBER= "c_numbers"; //$NON-NLS-1$ + /** The color key for everthing in C code for which no other color is specified. */ String C_DEFAULT= "c_default"; //$NON-NLS-1$ - + + /** The color key for preprocessor directives. */ + String PP_DIRECTIVE= "pp_directive"; //$NON-NLS-1$ + /** The color key for preprocessor text not colored otherwise. */ + String PP_DEFAULT= "pp_default"; //$NON-NLS-1$ + /** The color key for preprocessor include files. */ + String PP_HEADER= "pp_header"; //$NON-NLS-1$ + /** * The color key for task tags in C comments * (value "c_comment_task_tag"). diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/PartitionDamager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/PartitionDamager.java new file mode 100644 index 00000000000..06099b8246c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/PartitionDamager.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * 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.internal.ui.text; + +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.presentation.IPresentationDamager; + +/** + * A simple presentation damager always damaging the whole partition. + * This is necessary if the partition contains multiline highlight regions. + * + * @since 4.0 + */ +public class PartitionDamager implements IPresentationDamager { + + /* + * @see org.eclipse.jface.text.presentation.IPresentationDamager#getDamageRegion(org.eclipse.jface.text.ITypedRegion, org.eclipse.jface.text.DocumentEvent, boolean) + */ + public IRegion getDamageRegion(ITypedRegion partition, DocumentEvent event, + boolean documentPartitioningChanged) { + return partition; + } + + /* + * @see org.eclipse.jface.text.presentation.IPresentationDamager#setDocument(org.eclipse.jface.text.IDocument) + */ + public void setDocument(IDocument document) { + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/PreprocessorRule.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/PreprocessorRule.java index 0805c04a5d9..e6e66eb87cb 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/PreprocessorRule.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/PreprocessorRule.java @@ -7,15 +7,15 @@ * * Contributors: * QNX Software Systems - Initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.text; import org.eclipse.jface.text.rules.ICharacterScanner; -import org.eclipse.jface.text.rules.IWordDetector; -import org.eclipse.jface.text.rules.WordRule; -import org.eclipse.jface.text.rules.IRule; import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WordRule; /** * Implementation of IRule for C/C++ preprocessor scanning. @@ -23,9 +23,10 @@ import org.eclipse.jface.text.rules.Token; * at the beginning of the string, then '#' sign, then 0 or more whitespaces * again, and then directive itself. */ -public class PreprocessorRule extends WordRule implements IRule { +public class PreprocessorRule extends WordRule { private StringBuffer fBuffer = new StringBuffer(); + private IToken fMalformedToken; /** * Creates a rule which, with the help of a word detector, will return the token @@ -56,6 +57,33 @@ public class PreprocessorRule extends WordRule implements IRule { super(detector, defaultToken); } + /** + * Creates a rule which, with the help of an word detector, will return the token + * associated with the detected word. If no token has been associated, the + * specified default token will be returned. + * + * @param detector the word detector to be used by this rule, may not be null + * @param defaultToken the default token to be returned on success + * if nothing else is specified, may not be null + * @param malformedToken the token to be returned if the directive is malformed + * + * @see WordRule#addWord + */ + public PreprocessorRule(IWordDetector detector, IToken defaultToken, IToken malformedToken) { + super(detector, defaultToken); + fMalformedToken= malformedToken; + } + + /* + * @see org.eclipse.jface.text.rules.WordRule#addWord(java.lang.String, org.eclipse.jface.text.rules.IToken) + */ + public void addWord(String word, IToken token) { + if (word.charAt(0) == '#') { + word= word.substring(1); + } + super.addWord(word, token); + } + /* * @see IRule#evaluate */ @@ -64,14 +92,10 @@ public class PreprocessorRule extends WordRule implements IRule { int nCharsToRollback = 0; boolean hashSignDetected = false; - if (scanner.getColumn() > 0) - return Token.UNDEFINED; - do { c = scanner.read(); nCharsToRollback++; - } while (Character.isWhitespace((char) c)); - + } while (c == ' ' || c == '\t'); // Di- and trigraph support if (c == '#') { @@ -98,20 +122,29 @@ public class PreprocessorRule extends WordRule implements IRule { do { c = scanner.read(); - } while (Character.isWhitespace((char) c)); + } while (c == ' ' || c == '\t'); fBuffer.setLength(0); - - do { - fBuffer.append((char) c); - c = scanner.read(); - } while (Character.isJavaIdentifierPart((char) c)); - - scanner.unread(); - - IToken token = (IToken) fWords.get("#" + fBuffer.toString()); //$NON-NLS-1$ + + if (c != '#') { + if (fDetector.isWordStart((char) c)) { + do { + fBuffer.append((char) c); + c = scanner.read(); + } while (fDetector.isWordPart((char) c)); + } + scanner.unread(); + } + IToken token = (IToken) fWords.get(fBuffer.toString()); if (token != null) return token; + + if (fMalformedToken != null) { + do { + c = scanner.read(); + } while (c != ICharacterScanner.EOF); + return fMalformedToken; + } return fDefaultToken; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWhitespaceDetector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWhitespaceDetector.java index 1fb2534d0ef..e5f70f29a3a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWhitespaceDetector.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWhitespaceDetector.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000 2005 IBM Corporation and others. + * Copyright (c) 2000, 2006 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 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * QNX Software System + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.text.util; @@ -15,14 +16,22 @@ import org.eclipse.jface.text.rules.IWhitespaceDetector; /** - * A C aware white space detector. + * A simple white space detector. */ public class CWhitespaceDetector implements IWhitespaceDetector { - /** - * @see IWhitespaceDetector#isWhitespace + /* + * @see IWhitespaceDetector#isWhitespace(char) */ public boolean isWhitespace(char c) { - return Character.isWhitespace(c); + switch (c) { + case ' ': + case '\t': + case '\r': + case '\n': + return true; + default: + return Character.isWhitespace(c); + } } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java index cba76ad143e..cb9cb590126 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java @@ -163,7 +163,106 @@ public class PreferenceConstants { * @since 4.0 */ public final static String EDITOR_C_KEYWORD_ITALIC= ICColorConstants.C_KEYWORD + EDITOR_ITALIC_SUFFIX; + + /** + * A named preference that holds the color used to render preprocessor directives. + *

+ * Value is of type String. A RGB color value encoded as a string + * using class PreferenceConverter + *

+ * + * @see org.eclipse.jface.resource.StringConverter + * @see org.eclipse.jface.preference.PreferenceConverter + * @since 4.0 + */ + public final static String EDITOR_PP_DIRECTIVE_COLOR= ICColorConstants.PP_DIRECTIVE; + + /** + * A named preference that controls whether preprocessor directives are rendered in bold. + *

+ * Value is of type Boolean. + *

+ * + * @since 4.0 + */ + public final static String EDITOR_PP_DIRECTIVE_BOLD= ICColorConstants.PP_DIRECTIVE + EDITOR_BOLD_SUFFIX; + + /** + * A named preference that controls whether preprocessor directives are rendered in italic. + *

+ * Value is of type Boolean. + *

+ * + * @since 4.0 + */ + public final static String EDITOR_PP_DIRECTIVE_ITALIC= ICColorConstants.PP_DIRECTIVE + EDITOR_ITALIC_SUFFIX; + + /** + * A named preference that holds the color used to render headers. + *

+ * Value is of type String. A RGB color value encoded as a string + * using class PreferenceConverter + *

+ * + * @see org.eclipse.jface.resource.StringConverter + * @see org.eclipse.jface.preference.PreferenceConverter + * @since 4.0 + */ + public final static String EDITOR_PP_HEADER_COLOR= ICColorConstants.PP_HEADER; + + /** + * A named preference that controls whether headers are rendered in bold. + *

+ * Value is of type Boolean. + *

+ * + * @since 4.0 + */ + public final static String EDITOR_PP_HEADER_BOLD= ICColorConstants.PP_HEADER + EDITOR_BOLD_SUFFIX; + + /** + * A named preference that controls whether number are rendered in italic. + *

+ * Value is of type Boolean. + *

+ * + * @since 4.0 + */ + public final static String EDITOR_PP_HEADER_ITALIC= ICColorConstants.PP_HEADER + EDITOR_ITALIC_SUFFIX; + /** + * A named preference that holds the color used to render preprocessor text. + *

+ * Value is of type String. A RGB color value encoded as a string + * using class PreferenceConverter + *

+ * + * @see org.eclipse.jface.resource.StringConverter + * @see org.eclipse.jface.preference.PreferenceConverter + * @since 4.0 + */ + public final static String EDITOR_PP_DEFAULT_COLOR= ICColorConstants.PP_DEFAULT; + + /** + * A named preference that controls whether preprocessor text is rendered in bold. + *

+ * Value is of type Boolean. + *

+ * + * @since 4.0 + */ + public final static String EDITOR_PP_DEFAULT_BOLD= ICColorConstants.PP_DEFAULT + EDITOR_BOLD_SUFFIX; + + /** + * A named preference that controls whether preprocessor text is rendered in italic. + *

+ * Value is of type Boolean. + *

+ * + * @since 4.0 + */ + public final static String EDITOR_PP_DEFAULT_ITALIC= ICColorConstants.PP_DEFAULT + EDITOR_ITALIC_SUFFIX; + /** * A named preference that holds the color used to render builtin types. *

@@ -296,39 +395,6 @@ public class PreferenceConstants { */ public final static String EDITOR_C_NUMBER_ITALIC= ICColorConstants.C_NUMBER + EDITOR_ITALIC_SUFFIX; - /** - * A named preference that holds the color used to render headers. - *

- * Value is of type String. A RGB color value encoded as a string - * using class PreferenceConverter - *

- * - * @see org.eclipse.jface.resource.StringConverter - * @see org.eclipse.jface.preference.PreferenceConverter - * @since 4.0 - */ - public final static String EDITOR_C_HEADER_COLOR= ICColorConstants.C_HEADER; - - /** - * A named preference that controls whether headers are rendered in bold. - *

- * Value is of type Boolean. - *

- * - * @since 4.0 - */ - public final static String EDITOR_C_HEADER_BOLD= ICColorConstants.C_HEADER + EDITOR_BOLD_SUFFIX; - - /** - * A named preference that controls whether number are rendered in italic. - *

- * Value is of type Boolean. - *

- * - * @since 4.0 - */ - public final static String EDITOR_C_HEADER_ITALIC= ICColorConstants.C_HEADER + EDITOR_ITALIC_SUFFIX; - /** * A named preference that holds the color used to render braces. *

@@ -956,9 +1022,17 @@ public class PreferenceConstants { store.setDefault(EDITOR_C_NUMBER_BOLD, false); store.setDefault(EDITOR_C_NUMBER_ITALIC, false); - PreferenceConverter.setDefault(store, EDITOR_C_HEADER_COLOR, new RGB(42, 0, 255)); - store.setDefault(EDITOR_C_HEADER_BOLD, false); - store.setDefault(EDITOR_C_HEADER_ITALIC, false); + PreferenceConverter.setDefault(store, EDITOR_PP_DIRECTIVE_COLOR, new RGB(127, 0, 85)); + store.setDefault(EDITOR_PP_DIRECTIVE_BOLD, true); + store.setDefault(EDITOR_PP_DIRECTIVE_ITALIC, false); + + PreferenceConverter.setDefault(store, EDITOR_PP_HEADER_COLOR, new RGB(42, 0, 255)); + store.setDefault(EDITOR_PP_HEADER_BOLD, false); + store.setDefault(EDITOR_PP_HEADER_ITALIC, false); + + PreferenceConverter.setDefault(store, EDITOR_PP_DEFAULT_COLOR, new RGB(0, 0, 0)); + store.setDefault(EDITOR_PP_DEFAULT_BOLD, false); + store.setDefault(EDITOR_PP_DEFAULT_ITALIC, false); // folding store.setDefault(PreferenceConstants.EDITOR_FOLDING_ENABLED, false); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ICPartitions.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ICPartitions.java index 861eba0df48..396bd1933be 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ICPartitions.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/ICPartitions.java @@ -41,4 +41,9 @@ public interface ICPartitions { * The identifier of the C character partition content type. */ String C_CHARACTER= "__c_character"; //$NON-NLS-1$ + + /** + * The identifier of the C preprocessor partition content type. + */ + String C_PREPROCESSOR= "__c_preprocessor"; //$NON-NLS-1$ }