From 7cfc4446c33f6119a5bef00cb6f0390b1dc5e7ed Mon Sep 17 00:00:00 2001 From: Anton Leherbauer Date: Mon, 15 Oct 2007 14:53:25 +0000 Subject: [PATCH] Fix for 201548: [Editor] Need partition scanner for assembly content --- .../cdt/ui/tests/text/AsmPartitionerTest.java | 1198 +++++++++++++++++ .../cdt/ui/tests/text/TextTestSuite.java | 1 + core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF | 1 + core/org.eclipse.cdt.ui/plugin.properties | 2 +- core/org.eclipse.cdt.ui/plugin.xml | 6 +- .../asm/AsmDocumentSetupParticipant.java | 68 + .../ui/text/asm/AsmPartitionScanner.java | 693 ++++++++++ 7 files changed, 1965 insertions(+), 4 deletions(-) create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/AsmPartitionerTest.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmDocumentSetupParticipant.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/asm/AsmPartitionScanner.java diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/AsmPartitionerTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/AsmPartitionerTest.java new file mode 100644 index 00000000000..4eeafd2708e --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/AsmPartitionerTest.java @@ -0,0 +1,1198 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.ui.tests.text; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.IDocumentPartitioningListener; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.TypedRegion; +import org.eclipse.jface.text.rules.FastPartitioner; + +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.ui.text.asm.AsmPartitionScanner; + + +/** + * Tests to verify the Asm partitioning. + */ +public class AsmPartitionerTest extends TestCase { + + private Document fDocument; + protected boolean fDocumentPartitioningChanged; + + + public AsmPartitionerTest(String name) { + super(name); + } + + protected void setUp() { + fDocument= new Document("xxx\n/*xxx*/\nxxx\n/**xxx*/\nxxx\n/**/\nxxx\n/***/\nxxx"); + setupDefaultPartitioner(); + + fDocumentPartitioningChanged= false; + fDocument.addDocumentPartitioningListener(new IDocumentPartitioningListener() { + public void documentPartitioningChanged(IDocument document) { + fDocumentPartitioningChanged= true; + } + }); + } + + protected void setupDefaultPartitioner() { + setupPartitioner("", true); + + } + + protected void setupPartitioner(String lineCommentChars, boolean detectPreprocessor) { + IDocumentPartitioner partitioner= fDocument.getDocumentPartitioner(); + if (partitioner != null) { + partitioner.disconnect(); + } + String[] types= new String[] { + ICPartitions.C_MULTI_LINE_COMMENT, + ICPartitions.C_SINGLE_LINE_COMMENT, + ICPartitions.C_STRING, + ICPartitions.C_CHARACTER, + ICPartitions.C_PREPROCESSOR + }; + AsmPartitionScanner partitionScanner= new AsmPartitionScanner(); + partitionScanner.setLineCommentCharacters(lineCommentChars); + partitionScanner.setDetectPreprocessorDiretives(detectPreprocessor); + partitioner= new FastPartitioner(partitionScanner, types); + partitioner.connect(fDocument); + fDocument.setDocumentPartitioner(partitioner); + } + public static Test suite() { + return new TestSuite(AsmPartitionerTest.class); + } + + protected void tearDown () { + IDocumentPartitioner partitioner= fDocument.getDocumentPartitioner(); + if (partitioner != null) { + partitioner.disconnect(); + } + fDocument= null; + } + + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(16, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(29, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(33, 5, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(16, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(29, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(33, 3, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(16, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(29, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(33, 5, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(16, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(29, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(33, 2, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(35, 5, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(40, 2, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(16, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(29, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(33, 2, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(35, 5, ICPartitions.C_STRING), + new TypedRegion(40, 2, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(16, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(29, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(33, 2, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(35, 2, ICPartitions.C_CHARACTER), + new TypedRegion(37, 2, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(39, 5, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(44, 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 2, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(13, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(17, 5, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(12, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(20, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(25, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(29, 5, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(16, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(16, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(4, 18, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(22, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(27, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(31, 5, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 9, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(20, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + 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/*/***/" + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 5, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(5, 4, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(5, 1, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(6, 5, ICPartitions.C_MULTI_LINE_COMMENT), + 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/***/" + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 5, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(5, 4, IDocument.DEFAULT_CONTENT_TYPE), + 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), + 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/***/" + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + 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), + new TypedRegion(11, 1, IDocument.DEFAULT_CONTENT_TYPE), + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(16, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(29, 4, ICPartitions.C_MULTI_LINE_COMMENT), + 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), + new TypedRegion(4, 7, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(16, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(24, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(29, 4, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(33, 5, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(38, 5, ICPartitions.C_MULTI_LINE_COMMENT), + 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++) { + ITypedRegion result= fDocument.getPartition(expected.getOffset() + j); + 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()); + TypedRegion[] expectation1= { + new TypedRegion(0, 1, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(1, 10, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(11, 4, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(15, 4, 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, 5, ICPartitions.C_SINGLE_LINE_COMMENT), + new TypedRegion(5, 4, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(9, 11, 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); + + + 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); + + + } 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); + + 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); + + } 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, "*"); + fDocument.replace(fDocument.getLength(), 0, "\r\n *"); + 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, 8, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(8, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + } catch (BadLocationException x) { + assertTrue(false); + } + } + + 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"); + fDocument.replace(fDocument.getLength(), 0, "\""); + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, fDocument.getLength(), ICPartitions.C_STRING) + }; + 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); + + // insert escaped double quote + fDocument.replace(2, 0, "\\\""); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 6, ICPartitions.C_STRING), + new TypedRegion(6, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + // insert closing and opening double quote + fDocument.replace(2, 2, "\"\""); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + 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); + + // insert line continuation and newline + fDocument.replace(2, 2, "\\\r\n"); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 7, ICPartitions.C_STRING), + new TypedRegion(7, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + // delete line continuation + fDocument.replace(2, 1, ""); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + 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); + + } 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"); + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, fDocument.getLength(), ICPartitions.C_CHARACTER) + }; + checkPartitioning(expectation, result); + + fDocument.replace(fDocument.getLength(), 0, "yy"); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 2, ICPartitions.C_CHARACTER), + new TypedRegion(2, 2, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + // insert escaped single quote + fDocument.replace(1, 1, "\\"); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 3, ICPartitions.C_CHARACTER), + new TypedRegion(3, 1, IDocument.DEFAULT_CONTENT_TYPE) + }; + 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, "/* */"); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 21, ICPartitions.C_PREPROCESSOR), + new TypedRegion(21, 5, ICPartitions.C_MULTI_LINE_COMMENT), + }; + checkPartitioning(expectation, result); + + fDocument.replace(fDocument.getLength(), 0, "\nz"); + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, 21, ICPartitions.C_PREPROCESSOR), + new TypedRegion(21, 5, ICPartitions.C_MULTI_LINE_COMMENT), + new TypedRegion(26, 1, 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); + } + } + + public void testSingleLineComment_Hash() throws BadLocationException { + // to get single line comment partitions for # lines, + // we need to configure the partitioner + setupPartitioner("#", false); + fDocument.set("# single line comment"); + int p1= fDocument.getLength(); + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); + TypedRegion[] expectation= { + new TypedRegion(0, p1, ICPartitions.C_SINGLE_LINE_COMMENT) + }; + checkPartitioning(expectation, result); + + fDocument.replace(p1++, 0, "\nlabel: opcode arg1,arg2 "); + int p2= fDocument.getLength(); + fDocument.replace(p2, 0, "# end-of-line comment"); + int p3= fDocument.getLength(); + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, p1, ICPartitions.C_SINGLE_LINE_COMMENT), + new TypedRegion(p1, p2-p1, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(p2, p3-p2, ICPartitions.C_SINGLE_LINE_COMMENT) + }; + checkPartitioning(expectation, result); + } + + public void testSingleLineComment_Semicolon() throws BadLocationException { +// setupPartitioner(";", false); + fDocument.set("; single line comment"); + int p1= fDocument.getLength(); + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); + TypedRegion[] expectation= { + new TypedRegion(0, p1, ICPartitions.C_SINGLE_LINE_COMMENT) + }; + checkPartitioning(expectation, result); + + fDocument.replace(p1++, 0, "\nlabel: opcode arg1,#arg2 "); + int p2= fDocument.getLength(); + fDocument.replace(p2, 0, "; end-of-line comment"); + int p3= fDocument.getLength(); + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, p1, ICPartitions.C_SINGLE_LINE_COMMENT), + new TypedRegion(p1, p2-p1, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(p2, p3-p2, ICPartitions.C_SINGLE_LINE_COMMENT) + }; + checkPartitioning(expectation, result); + } + + public void testSingleLineComment_AtSign() throws BadLocationException { +// setupPartitioner("@", false); + fDocument.set("@ single line comment"); + int p1= fDocument.getLength(); + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); + TypedRegion[] expectation= { + new TypedRegion(0, p1, ICPartitions.C_SINGLE_LINE_COMMENT) + }; + checkPartitioning(expectation, result); + + fDocument.replace(p1++, 0, "\nlabel: opcode arg1,#arg2 "); + int p2= fDocument.getLength(); + fDocument.replace(p2, 0, "@ end-of-line comment"); + int p3= fDocument.getLength(); + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, p1, ICPartitions.C_SINGLE_LINE_COMMENT), + new TypedRegion(p1, p2-p1, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(p2, p3-p2, ICPartitions.C_SINGLE_LINE_COMMENT) + }; + checkPartitioning(expectation, result); + + // cmp dividend, #0 @ Early termination? + fDocument.replace(p3++, 0, "\ncmp dividend, #0 "); + int p4= fDocument.getLength(); + fDocument.replace(p4, 0, "@ Early termination?"); + int p5= fDocument.getLength(); + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, p1, ICPartitions.C_SINGLE_LINE_COMMENT), + new TypedRegion(p1, p2-p1, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(p2, p3-p2, ICPartitions.C_SINGLE_LINE_COMMENT), + new TypedRegion(p3, p4-p3, IDocument.DEFAULT_CONTENT_TYPE), + new TypedRegion(p4, p5-p4, ICPartitions.C_SINGLE_LINE_COMMENT) + }; + checkPartitioning(expectation, result); +} + + public void testSingleLineComment_Star() throws BadLocationException { +// setupPartitioner("*", false); + fDocument.set("* single line comment"); + int p1= fDocument.getLength(); + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); + TypedRegion[] expectation= { + new TypedRegion(0, p1, ICPartitions.C_SINGLE_LINE_COMMENT) + }; + checkPartitioning(expectation, result); + + fDocument.replace(p1++, 0, "\nlabel: opcode arg1,arg2 "); + int p2= fDocument.getLength(); + fDocument.replace(p2, 0, "* no end-of-line comment"); + int p3= fDocument.getLength(); + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, p1, ICPartitions.C_SINGLE_LINE_COMMENT), + new TypedRegion(p1, p3-p1, IDocument.DEFAULT_CONTENT_TYPE), + }; + checkPartitioning(expectation, result); + } + + public void testNoSingleLineComment_Dollar() throws BadLocationException { + fDocument.set("$ no single line comment"); + int p1= fDocument.getLength(); + ITypedRegion[] result= fDocument.computePartitioning(0, fDocument.getLength()); + TypedRegion[] expectation= { + new TypedRegion(0, p1, IDocument.DEFAULT_CONTENT_TYPE) + }; + checkPartitioning(expectation, result); + + fDocument.replace(p1++, 0, "\nlabel: opcode arg1,arg2 "); + int p2= fDocument.getLength(); + fDocument.replace(p2, 0, "$ no end-of-line comment"); + int p3= fDocument.getLength(); + + result= fDocument.computePartitioning(0, fDocument.getLength()); + expectation= new TypedRegion[] { + new TypedRegion(0, p3, IDocument.DEFAULT_CONTENT_TYPE), + }; + checkPartitioning(expectation, result); + } + +} 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 1f7154ea0fe..9f8257c910e 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 @@ -25,6 +25,7 @@ public class TextTestSuite extends TestSuite { // partitioning tests addTest(PartitionTokenScannerTest.suite()); addTest(CPartitionerTest.suite()); + addTest(AsmPartitionerTest.suite()); // smart edit tests addTest(CAutoIndentTest.suite()); diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF index fa6dece76d9..24ad1f3cd5a 100644 --- a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF @@ -31,6 +31,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.internal.ui.search;x-internal:=true, org.eclipse.cdt.internal.ui.search.actions;x-internal:=true, org.eclipse.cdt.internal.ui.text;x-internal:=true, + org.eclipse.cdt.internal.ui.text.asm;x-internal:=true, org.eclipse.cdt.internal.ui.text.c.hover;x-internal:=true, org.eclipse.cdt.internal.ui.text.contentassist;x-internal:=true, org.eclipse.cdt.internal.ui.text.folding;x-internal:=true, diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties index 26fc977760a..2da7e660e01 100644 --- a/core/org.eclipse.cdt.ui/plugin.properties +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -276,8 +276,8 @@ CDTFileTypesProperty.name=File Types CDTLanguagesProperty.name=Language Mappings -cDocumentFactory=C Document Factory cDocumentSetupParticipant=C Document Setup Participant +asmDocumentSetupParticipant=Assembly Document Setup Participant defaultPathContainerPage=Default Path Container diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index b621b6c406f..2cf064725bd 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -509,11 +509,11 @@ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmDocumentSetupParticipant.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmDocumentSetupParticipant.java new file mode 100644 index 00000000000..8eb3f7e4224 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmDocumentSetupParticipant.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2007 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 org.eclipse.core.filebuffers.IDocumentSetupParticipant; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.rules.FastPartitioner; + +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.ui.text.asm.AsmPartitionScanner; + +/** + * Document setup participant for asesembly content. + */ +public class AsmDocumentSetupParticipant implements IDocumentSetupParticipant, IExecutableExtension { + /** + * Manadatory default constructor. + */ + public AsmDocumentSetupParticipant() { + } + + /* + * @see org.eclipse.core.filebuffers.IDocumentSetupParticipant#setup(org.eclipse.jface.text.IDocument) + */ + public void setup(IDocument document) { + IDocumentPartitioner partitioner= createDocumentPartitioner(); + if (document instanceof IDocumentExtension3) { + IDocumentExtension3 extension3= (IDocumentExtension3) document; + extension3.setDocumentPartitioner(ICPartitions.C_PARTITIONING, partitioner); + } else { + document.setDocumentPartitioner(partitioner); + } + partitioner.connect(document); + } + + private IDocumentPartitioner createDocumentPartitioner() { + String[] types= new String[] { + ICPartitions.C_MULTI_LINE_COMMENT, + ICPartitions.C_SINGLE_LINE_COMMENT, + ICPartitions.C_STRING, + ICPartitions.C_CHARACTER, + ICPartitions.C_PREPROCESSOR + }; + return new FastPartitioner(new AsmPartitionScanner(), types); + } + + /* + * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object) + */ + public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { + // prepared for partitioner configuration + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/asm/AsmPartitionScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/asm/AsmPartitionScanner.java new file mode 100644 index 00000000000..6f73ac032b9 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/asm/AsmPartitionScanner.java @@ -0,0 +1,693 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * QNX Software System + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.text.asm; + + +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; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.Token; + +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.ui.text.BufferedDocumentScanner; + + +/** + * This scanner recognizes + *
    + *
  • C multi line comments
  • + *
  • Assembly line comments
  • + *
  • C string literals
  • + *
  • Assembly character literals
  • + *
  • C preprocessor directives
  • + *
+ * Default supported line start comment characters are ';', '!', '|' and '@'. + *

+ * A simple heuristic is used to detect valid line end comment characters: If a + * character known to be a potential line end comment character is used as a + * line start comment char, this character is considered a valid line end + * comment character, too. If e.g. a '@' is used to introduce a line start + * comment it is also recognized as a line end comment introducer afterwards. + *

+ */ +public final class AsmPartitionScanner implements IPartitionTokenScanner, ICPartitions { + + /** + * Characters not applicable for line start comments. + */ + private static final String NON_LINE_COMMENT_CHARS = "\t #/_$.%()'\""; //$NON-NLS-1$ + /** + * Characters known to be used as line end comments. + */ + private static final String KNOWN_LINE_END_COMMENT_CHARS = "#;@|!"; //$NON-NLS-1$ + + // states + private static final int CCODE= 0; + private static final int SINGLE_LINE_COMMENT= 1; + 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, 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 BufferedDocumentScanner fScanner= new BufferedDocumentScanner(1000); + + /** The offset of the last returned token. */ + private int fTokenOffset; + /** The length of the last returned token. */ + private int fTokenLength; + + /** The state of the scanner. */ + private int fState; + /** The last significant character read. */ + 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; + + 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_PREPROCESSOR), + new Token(C_MULTI_LINE_COMMENT) + }; + + private String fLineCommentChars= ""; //$NON-NLS-1$ + private String fLineEndCommentChars= ""; //$NON-NLS-1$ + private String fLineStartCommentChars= ";!|@"; //$NON-NLS-1$ + private boolean fDetectPreprocessor= true; + + public AsmPartitionScanner() { + } + + /** + * Configure the set of default line comment characters. + *

+ * These characters are considered line comment introducers at any position + * in the code. + *

+ * + * @param chars + */ + public void setLineCommentCharacters(String chars) { + fLineCommentChars= chars != null ? chars : ""; //$NON-NLS-1$ + } + + /** + * Configure the set of default line start comment characters. + *

+ * These characters are considered line comment introducers only as first + * non-whitespace character on the line. + *

+ * + * @param chars + */ + public void setLineStartCommentCharacters(String chars) { + fLineStartCommentChars= chars != null ? chars : ""; //$NON-NLS-1$ + } + + /** + * Configure the set of default line end comment characters. + *

+ * These characters are considered line comment introducers at the end of a + * instruction line. + *

+ * + * @param chars + */ + public void setLineEndCommentCharacters(String chars) { + fLineEndCommentChars= chars != null ? chars : ""; //$NON-NLS-1$ + } + + /** + * Configure whether preprocessor directives should be detected. + * + * @param detectPreprocessor + */ + public void setDetectPreprocessorDiretives(boolean detectPreprocessor) { + fDetectPreprocessor= detectPreprocessor; + } + + /* + * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken() + */ + public IToken nextToken() { + + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + + while (true) { + final int ch= fScanner.read(); + + 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; + } + + case '\r': + fFirstCharOnLine= true; + if (fLast == BACKSLASH) { + fLast= BACKSLASH_CR; + fTokenLength++; + continue; + } else if (fLast != CARRIAGE_RETURN) { + fLast= CARRIAGE_RETURN; + fTokenLength++; + continue; + } else { + // fLast == CARRIAGE_RETURN + switch (fState) { + case SINGLE_LINE_COMMENT: + case CHARACTER: + case STRING: + case PREPROCESSOR: + if (fTokenLength > 0) { + IToken token= fTokens[fState]; + + 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 && fLast != BACKSLASH_CR) { + return postFix(fState); + } + + default: + consume(); + continue; + } + + case ' ': + case '\t': + consume(); + continue; + + default: + if (fLast == CARRIAGE_RETURN) { + switch (fState) { + case SINGLE_LINE_COMMENT: + case CHARACTER: + case STRING: + case PREPROCESSOR: + + 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; + + case '#': + last= NONE; + newState= PREPROCESSOR; + break; + + default: + last= NONE; + newState= CCODE; + break; + } + + fLast= NONE; // ignore fLast + return preFix(fState, newState, last, 1); + + case CCODE: + if (fDetectPreprocessor && 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; + + default: + break; + } + } + } + + // states + switch (fState) { + case CCODE: + if (fLast == NONE) { + boolean isLineComment= false; + if (ch == '#' && fDetectPreprocessor && isFirstCharOnLine) { + // don't consume as line comment + } else if (fLineCommentChars.indexOf(ch) >= 0 || (isFirstCharOnLine && fLineStartCommentChars.indexOf(ch) >= 0) || (!isFirstCharOnLine && fLineEndCommentChars.indexOf(ch) >= 0)) { + isLineComment= true; + } else if (isFirstCharOnLine && !Character.isLetterOrDigit((char)ch) && NON_LINE_COMMENT_CHARS.indexOf(ch) < 0) { + fLineStartCommentChars += (char)ch; + isLineComment= true; + } + if (isLineComment) { + if (isFirstCharOnLine && fLineEndCommentChars.indexOf(ch) < 0 && KNOWN_LINE_END_COMMENT_CHARS.indexOf(ch) >= 0) { + fLineEndCommentChars += (char)ch; + } + if (fTokenLength - getLastLength(fLast) > 0) { + return preFix(CCODE, SINGLE_LINE_COMMENT, NONE, 1); + } else { + preFix(CCODE, SINGLE_LINE_COMMENT, NONE, 1); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + } + break; + } + } + + switch (ch) { + case '/': + // unsupported: C++ line comment +// if (fLast == SLASH) { +// if (fTokenLength - getLastLength(fLast) > 0) { +// return preFix(CCODE, SINGLE_LINE_COMMENT, NONE, 2); +// } else { +// preFix(CCODE, SINGLE_LINE_COMMENT, NONE, 2); +// fTokenOffset += fTokenLength; +// fTokenLength= fPrefixLength; +// break; +// } +// } else { + fTokenLength++; + fLast= SLASH; + break; +// } + + case '*': + if (fLast == SLASH) { + if (fTokenLength - getLastLength(fLast) > 0) { + return preFix(CCODE, MULTI_LINE_COMMENT, SLASH_STAR, 2); + } else { + preFix(CCODE, MULTI_LINE_COMMENT, SLASH_STAR, 2); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + } else { + 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; + } + + 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; + } + + case '#': + if (fDetectPreprocessor && 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 '\\': + 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) { + if (fTokenLength - getLastLength(fLast) > 0) { + return preFix(fState, PREPROCESSOR_MULTI_LINE_COMMENT, SLASH_STAR, 2); + } else { + preFix(fState, PREPROCESSOR_MULTI_LINE_COMMENT, SLASH_STAR, 2); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + } else { + consume(); + break; + } + default: + consume(); + break; + } + break; + + case PREPROCESSOR_MULTI_LINE_COMMENT: + switch (ch) { + case '*': + fTokenLength++; + fLast= STAR; + break; + + case '/': + if (fLast == STAR) { + IToken token= postFix(fState); + fState= PREPROCESSOR; + return token; + } + consume(); + break; + + default: + consume(); + break; + } + break; + + case MULTI_LINE_COMMENT: + switch (ch) { + case '*': + fTokenLength++; + fLast= STAR; + break; + + case '/': + if (fLast == STAR) { + return postFix(MULTI_LINE_COMMENT); + } else { + consume(); + break; + } + + default: + consume(); + break; + } + break; + + case STRING: + switch (ch) { + case '\\': + fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH; + fTokenLength++; + break; + + case '\"': + if (fLast != BACKSLASH) { + return postFix(STRING); + + } else { + consume(); + break; + } + + default: + consume(); + break; + } + break; + + case CHARACTER: + switch (ch) { + case '\\': + fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH; + fTokenLength++; + if (fLast != BACKSLASH) { + return preFix(CHARACTER, CCODE, NONE, 1); + } + break; + + default: + return postFix(CHARACTER); + } + break; + } + } + } + + private static final int getLastLength(int last) { + switch (last) { + default: + return -1; + + case NONE: + return 0; + + case CARRIAGE_RETURN: + case BACKSLASH: + case SLASH: + case STAR: + return 1; + + case SLASH_STAR: + case BACKSLASH_CR: + return 2; + + } + } + + private final void consume() { + fTokenLength++; + fLast= NONE; + } + + private final IToken postFix(int state) { + fTokenLength++; + fLast= NONE; + fState= CCODE; + fPrefixLength= 0; + return fTokens[state]; + } + + 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; + } + + private static int getState(String contentType) { + + if (contentType == null) + return CCODE; + + else if (contentType.equals(C_SINGLE_LINE_COMMENT)) + return SINGLE_LINE_COMMENT; + + else if (contentType.equals(C_MULTI_LINE_COMMENT)) + return MULTI_LINE_COMMENT; + + else if (contentType.equals(C_STRING)) + return STRING; + + else if (contentType.equals(C_CHARACTER)) + return CHARACTER; + + else if (contentType.equals(C_PREPROCESSOR)) + return PREPROCESSOR; + + else + return CCODE; + } + + /* + * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int) + */ + public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) { + + fScanner.setRange(document, offset, length); + fTokenOffset= partitionOffset; + fTokenLength= 0; + fPrefixLength= offset - partitionOffset; + fLast= NONE; + + if (offset == partitionOffset) { + // restart at beginning of partition + fState= CCODE; + } else { + fState= getState(contentType); + } + + try { + int column= fScanner.getColumn(); + fFirstCharOnLine= column == 0 || document.get(offset-column, column).trim().length() == 0; + } catch (BadLocationException exc) { + fFirstCharOnLine= true; + } + } + + /* + * @see ITokenScanner#setRange(IDocument, int, int) + */ + public void setRange(IDocument document, int offset, int length) { + + fScanner.setRange(document, offset, length); + fTokenOffset= offset; + fTokenLength= 0; + fPrefixLength= 0; + 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; + } + } + + /* + * @see ITokenScanner#getTokenLength() + */ + public int getTokenLength() { + return fTokenLength; + } + + /* + * @see ITokenScanner#getTokenOffset() + */ + public int getTokenOffset() { + return fTokenOffset; + } + +}