diff options
author | bellingard <bellingard@gmail.com> | 2010-10-21 14:09:13 +0000 |
---|---|---|
committer | bellingard <bellingard@gmail.com> | 2010-10-21 14:09:13 +0000 |
commit | a16fe9d1448070c61f8eb7d43369643b666cf71b (patch) | |
tree | fcd63f74cb06c1d08ec6aacec854d569d9e528ae /sonar-channel/src | |
parent | 938b174bc222412d372730d64c23117100afefaf (diff) | |
download | sonarqube-a16fe9d1448070c61f8eb7d43369643b666cf71b.tar.gz sonarqube-a16fe9d1448070c61f8eb7d43369643b666cf71b.zip |
[SONAR-1875] Improve CodeReaderFilter with channel capabilities
http://jira.codehaus.org/browse/SONAR-1875
Diffstat (limited to 'sonar-channel/src')
8 files changed, 206 insertions, 45 deletions
diff --git a/sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java b/sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java index c68265a1d33..dabe5b7f4aa 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java +++ b/sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java @@ -35,7 +35,7 @@ public final class ChannelCodeReaderFilter<OUTPUT> extends CodeReaderFilter<OUTP private CodeReader internalCodeReader; /** - * Creates a CodeReaderFilter that will use the provided Channels to filter the character stream it gets from its reader. + * Creates a CodeReaderFilter that will use the provided Channels to filter the character stream it gets from its reader. * * @param channels * the different channels @@ -65,7 +65,7 @@ public final class ChannelCodeReaderFilter<OUTPUT> extends CodeReaderFilter<OUTP @Override public void setReader(Reader reader) { super.setReader(reader); - internalCodeReader = new CodeReader(reader); + internalCodeReader = new CodeReader(reader, getConfiguration()); } /** diff --git a/sonar-channel/src/main/java/org/sonar/channel/ChannelDispatcher.java b/sonar-channel/src/main/java/org/sonar/channel/ChannelDispatcher.java index f307c2c3335..6ebb0507373 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/ChannelDispatcher.java +++ b/sonar-channel/src/main/java/org/sonar/channel/ChannelDispatcher.java @@ -30,12 +30,15 @@ public class ChannelDispatcher<OUTPUT> extends Channel<OUTPUT> { private static final Logger logger = LoggerFactory.getLogger(ChannelDispatcher.class);
private final boolean failIfNoChannelToConsumeOneCharacter;
+ @SuppressWarnings("rawtypes")
private final Channel[] channels;
+ @SuppressWarnings("rawtypes")
public ChannelDispatcher(List<Channel> tokenizers) {
this(tokenizers, false);
}
+ @SuppressWarnings("rawtypes")
public ChannelDispatcher(List<Channel> tokenizers, boolean failIfNoChannelToConsumeOneCharacter) {
this.channels = tokenizers.toArray(new Channel[0]); // NOSONAR, lack of performance is not an issue here
this.failIfNoChannelToConsumeOneCharacter = failIfNoChannelToConsumeOneCharacter;
@@ -53,8 +56,7 @@ public class ChannelDispatcher<OUTPUT> extends Channel<OUTPUT> { }
if ( !channelConsumed) {
String message = "None of the channel has been able to handle character '" + (char) code.peek() + "' (decimal value " + code.peek()
- + ") at line "
- + code.getLinePosition() + ", column " + code.getColumnPosition();
+ + ") at line " + code.getLinePosition() + ", column " + code.getColumnPosition();
if (failIfNoChannelToConsumeOneCharacter) {
throw new IllegalStateException(message);
}
diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java b/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java index d308a48104a..a8433264b7a 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java +++ b/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java @@ -41,39 +41,35 @@ public class CodeBuffer implements CharSequence { private final Reader code; private int lastChar = -1; private Cursor cursor; - private final static int DEFAULT_BUFFER_CAPACITY = 8000; private int bufferCapacity; private char[] buffer; private int bufferPosition = 0; private int bufferSize = 0; private static final char LF = '\n'; private static final char CR = '\r'; + private int tabWidth; + private CodeReaderConfiguration configuration; + private boolean recordingMode = false; private StringBuilder recordedCharacters = new StringBuilder(); - public CodeBuffer(Reader code, CodeReaderFilter<?>... codeReaderFilters) { - this(code, DEFAULT_BUFFER_CAPACITY, codeReaderFilters); - } - - private CodeBuffer(Reader initialCodeReader, int bufferCapacity, CodeReaderFilter<?>... codeReaderFilters) { + protected CodeBuffer(Reader initialCodeReader, CodeReaderConfiguration configuration) { + this.configuration = configuration; lastChar = -1; cursor = new Cursor(); - this.bufferCapacity = bufferCapacity; + bufferCapacity = configuration.getBufferCapacity(); + tabWidth = configuration.getTabWidth(); buffer = new char[bufferCapacity]; Reader reader = initialCodeReader; - for (CodeReaderFilter<?> codeReaderFilter : codeReaderFilters) { + for (CodeReaderFilter<?> codeReaderFilter : configuration.getCodeReaderFilters()) { reader = new Filter(reader, codeReaderFilter); } this.code = reader; fillBuffer(); } - public CodeBuffer(String code, CodeReaderFilter<?>... codeReaderFilters) { - this(new StringReader(code), codeReaderFilters); - } - - protected CodeBuffer(String code, int bufferCapacity, CodeReaderFilter<?>... codeReaderFilters) { - this(new StringReader(code), bufferCapacity, codeReaderFilters); + protected CodeBuffer(String code, CodeReaderConfiguration configuration) { + this(new StringReader(code), configuration); } /** @@ -94,6 +90,8 @@ public class CodeBuffer implements CharSequence { cursor.line++; } cursor.column = 0; + } else if (character == '\t') { + cursor.column += tabWidth; } else { cursor.column++; } @@ -263,6 +261,7 @@ public class CodeBuffer implements CharSequence { public Filter(Reader in, CodeReaderFilter<?> codeReaderFilter) { super(in); this.codeReaderFilter = codeReaderFilter; + this.codeReaderFilter.setConfiguration(CodeBuffer.this.configuration.cloneWithoutCodeReaderFilters()); this.codeReaderFilter.setReader(in); } diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java b/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java index af4ade884d0..73a2172fbeb 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java +++ b/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java @@ -37,26 +37,38 @@ public class CodeReader extends CodeBuffer { * Constructor needed to be backward compatible (before using CodeReaderFilter) */ public CodeReader(Reader code) { - super(code, new CodeReaderFilter[] {}); + super(code, new CodeReaderConfiguration()); } /* * Constructor needed to be backward compatible (before using CodeReaderFilter) */ public CodeReader(String code) { - super(code, new CodeReaderFilter[] {}); + super(code, new CodeReaderConfiguration()); } - public CodeReader(Reader code, CodeReaderFilter... codeReaderFilters) { - super(code, codeReaderFilters); - } - - public CodeReader(String code, CodeReaderFilter... codeReaderFilters) { - super(code, codeReaderFilters); + /** + * Creates a code reader with specific configuration parameters. + * + * @param code + * the Reader to read code from + * @param configuration + * the configuration parameters + */ + public CodeReader(Reader code, CodeReaderConfiguration configuration) { + super(code, configuration); } - protected CodeReader(String code, int bufferCapacity, CodeReaderFilter... codeReaderFilters) { - super(code, bufferCapacity, codeReaderFilters); + /** + * Creates a code reader with specific configuration parameters. + * + * @param code + * the code itself + * @param configuration + * the configuration parameters + */ + public CodeReader(String code, CodeReaderConfiguration configuration) { + super(code, configuration); } /** @@ -113,7 +125,7 @@ public class CodeReader extends CodeBuffer { } /** - * @deprecated see peekTo(EndMatcher matcher, Appendable appendable) + * @see peekTo(EndMatcher matcher, Appendable appendable) */ @Deprecated public final String peekTo(EndMatcher matcher) { @@ -123,7 +135,7 @@ public class CodeReader extends CodeBuffer { } /** - * @deprecated see popTo(Matcher matcher, Appendable appendable) + * @see popTo(Matcher matcher, Appendable appendable) */ @Deprecated public final void popTo(EndMatcher matcher, Appendable appendable) { diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java b/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java new file mode 100644 index 00000000000..1f837aea4ba --- /dev/null +++ b/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java @@ -0,0 +1,90 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.channel; + +/** + * Configuration parameters used by a CodeReader to handle some specificities. + */ +public class CodeReaderConfiguration { + + private final static int DEFAULT_BUFFER_CAPACITY = 8000; + + private final static int DEFAULT_TAB_WIDTH = 1; + + private int bufferCapacity = DEFAULT_BUFFER_CAPACITY; + + private int tabWidth = DEFAULT_TAB_WIDTH; + + private CodeReaderFilter<?>[] codeReaderFilters = new CodeReaderFilter<?>[0]; + + /** + * @return the bufferCapacity + */ + public int getBufferCapacity() { + return bufferCapacity; + } + + /** + * @param bufferCapacity + * the bufferCapacity to set + */ + public void setBufferCapacity(int bufferCapacity) { + this.bufferCapacity = bufferCapacity; + } + + /** + * @return the tabWidth + */ + public int getTabWidth() { + return tabWidth; + } + + /** + * @param tabWidth + * the tabWidth to set + */ + public void setTabWidth(int tabWidth) { + this.tabWidth = tabWidth; + } + + /** + * @return the codeReaderFilters + */ + @SuppressWarnings("rawtypes") + public CodeReaderFilter[] getCodeReaderFilters() { + return codeReaderFilters; + } + + /** + * @param codeReaderFilters + * the codeReaderFilters to set + */ + public void setCodeReaderFilters(CodeReaderFilter<?>... codeReaderFilters) { + this.codeReaderFilters = codeReaderFilters; + } + + public CodeReaderConfiguration cloneWithoutCodeReaderFilters() { + CodeReaderConfiguration clone = new CodeReaderConfiguration(); + clone.setBufferCapacity(bufferCapacity); + clone.setTabWidth(tabWidth); + return clone; + } + +} diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeReaderFilter.java b/sonar-channel/src/main/java/org/sonar/channel/CodeReaderFilter.java index 7b5106b153f..d152783a17b 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/CodeReaderFilter.java +++ b/sonar-channel/src/main/java/org/sonar/channel/CodeReaderFilter.java @@ -39,6 +39,8 @@ public abstract class CodeReaderFilter<OUTPUT> { private OUTPUT output; + private CodeReaderConfiguration configuration; + public CodeReaderFilter() { } @@ -85,6 +87,25 @@ public abstract class CodeReaderFilter<OUTPUT> { } /** + * Returns the configuration used for the CodeReader + * + * @return the configuration + */ + public CodeReaderConfiguration getConfiguration() { + return configuration; + } + + /** + * Sets the configuration that must be used by the CodeReader + * + * @param configuration + * the configuration to set + */ + public void setConfiguration(CodeReaderConfiguration configuration) { + this.configuration = configuration; + } + + /** * This method implements the filtering logic, that is: * <ul> * <li> diff --git a/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java b/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java index ab1183806c0..d9ce7fe570b 100644 --- a/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java +++ b/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java @@ -19,8 +19,8 @@ */ package org.sonar.channel; +import static junit.framework.Assert.assertEquals; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import java.io.IOException; @@ -30,9 +30,11 @@ import org.junit.Test; public class CodeBufferTest { + private CodeReaderConfiguration defaulConfiguration = new CodeReaderConfiguration(); + @Test public void testPop() { - CodeBuffer code = new CodeBuffer("pa"); + CodeBuffer code = new CodeBuffer("pa", defaulConfiguration); assertThat((char) code.pop(), is('p')); assertThat((char) code.pop(), is('a')); assertThat(code.pop(), is( -1)); @@ -40,7 +42,7 @@ public class CodeBufferTest { @Test public void testPeek() { - CodeBuffer code = new CodeBuffer("pa"); + CodeBuffer code = new CodeBuffer("pa", defaulConfiguration); assertThat((char) code.peek(), is('p')); assertThat((char) code.peek(), is('p')); code.pop(); @@ -51,7 +53,7 @@ public class CodeBufferTest { @Test public void testLastCharacter() { - CodeBuffer reader = new CodeBuffer("bar"); + CodeBuffer reader = new CodeBuffer("bar", defaulConfiguration); assertThat(reader.lastChar(), is( -1)); reader.pop(); assertThat((char) reader.lastChar(), is('b')); @@ -59,7 +61,7 @@ public class CodeBufferTest { @Test public void testGetColumnAndLinePosition() { - CodeBuffer reader = new CodeBuffer("pa\nc\r\ns\r\n\r\n"); + CodeBuffer reader = new CodeBuffer("pa\nc\r\ns\r\n\r\n", defaulConfiguration); assertThat(reader.getColumnPosition(), is(0)); assertThat(reader.getLinePosition(), is(1)); reader.pop(); // p @@ -95,7 +97,7 @@ public class CodeBufferTest { @Test public void testStartAndStopRecording() { - CodeBuffer reader = new CodeBuffer("123456"); + CodeBuffer reader = new CodeBuffer("123456", defaulConfiguration); reader.pop(); assertEquals("", reader.stopRecording().toString()); @@ -109,20 +111,51 @@ public class CodeBufferTest { @Test public void testCharAt() { - CodeBuffer reader = new CodeBuffer("123456"); + CodeBuffer reader = new CodeBuffer("123456", defaulConfiguration); assertEquals('1', reader.charAt(0)); assertEquals('6', reader.charAt(5)); } @Test public void testCharAtIndexOutOfBoundsException() { - CodeBuffer reader = new CodeBuffer("12345"); + CodeBuffer reader = new CodeBuffer("12345", defaulConfiguration); assertEquals(reader.charAt(5), (char) -1); } @Test + public void testReadWithSpecificTabWidth() { + CodeReaderConfiguration configuration = new CodeReaderConfiguration(); + configuration.setTabWidth(4); + CodeBuffer reader = new CodeBuffer("pa\n\tc", configuration); + assertEquals('\n', reader.charAt(2)); + assertEquals('\t', reader.charAt(3)); + assertEquals('c', reader.charAt(4)); + assertThat(reader.getColumnPosition(), is(0)); + assertThat(reader.getLinePosition(), is(1)); + reader.pop(); // p + reader.pop(); // a + assertThat(reader.getColumnPosition(), is(2)); + assertThat(reader.getLinePosition(), is(1)); + reader.peek(); // \n + reader.lastChar(); // a + assertThat(reader.getColumnPosition(), is(2)); + assertThat(reader.getLinePosition(), is(1)); + reader.pop(); // \n + assertThat(reader.getColumnPosition(), is(0)); + assertThat(reader.getLinePosition(), is(2)); + reader.pop(); // \t + assertThat(reader.getColumnPosition(), is(4)); + assertThat(reader.getLinePosition(), is(2)); + reader.pop(); // c + assertThat(reader.getColumnPosition(), is(5)); + assertThat(reader.getLinePosition(), is(2)); + } + + @Test public void testCodeReaderFilter() throws Exception { - CodeBuffer code = new CodeBuffer("abcd12efgh34", new ReplaceNumbersFilter()); + CodeReaderConfiguration configuration = new CodeReaderConfiguration(); + configuration.setCodeReaderFilters(new ReplaceNumbersFilter()); + CodeBuffer code = new CodeBuffer("abcd12efgh34", configuration); // test #charAt assertEquals('a', code.charAt(0)); assertEquals('-', code.charAt(4)); @@ -149,7 +182,9 @@ public class CodeBufferTest { @Test public void testSeveralCodeReaderFilter() throws Exception { - CodeBuffer code = new CodeBuffer("abcd12efgh34", new ReplaceNumbersFilter(), new ReplaceCharFilter()); + CodeReaderConfiguration configuration = new CodeReaderConfiguration(); + configuration.setCodeReaderFilters(new ReplaceNumbersFilter(), new ReplaceCharFilter()); + CodeBuffer code = new CodeBuffer("abcd12efgh34", configuration); // test #charAt assertEquals('*', code.charAt(0)); assertEquals('-', code.charAt(4)); @@ -175,10 +210,12 @@ public class CodeBufferTest { } @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) public void testChannelCodeReaderFilter() throws Exception { // create a windowing channel that drops the 2 first characters, keeps 6 characters and drops the rest of the line - @SuppressWarnings({ "rawtypes", "unchecked" }) - CodeBuffer code = new CodeBuffer("0123456789\nABCDEFGHIJ", new ChannelCodeReaderFilter(new Object(), new WindowingChannel())); + CodeReaderConfiguration configuration = new CodeReaderConfiguration(); + configuration.setCodeReaderFilters(new ChannelCodeReaderFilter(new Object(), new WindowingChannel())); + CodeBuffer code = new CodeBuffer("0123456789\nABCDEFGHIJ", configuration); // test #charAt assertEquals('2', code.charAt(0)); assertEquals('7', code.charAt(5)); diff --git a/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java b/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java index 7c195bff527..874abd0033c 100644 --- a/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java +++ b/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java @@ -20,7 +20,6 @@ package org.sonar.channel; import static org.hamcrest.core.Is.is; -import static org.hamcrest.number.OrderingComparisons.lessThan; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -72,7 +71,6 @@ public class CodeReaderTest { CodeReader reader = new CodeReader(new StringReader("package org.sonar;")); StringBuilder result = new StringBuilder(); reader.popTo(new EndMatcher() { - public boolean match(int endFlag) { return 'r' == (char) endFlag; } @@ -86,7 +84,9 @@ public class CodeReaderTest { @Test public void testPeekToAndReachingTheBufferLimit() { - CodeReader reader = new CodeReader("word1 word2 word2", 10); + CodeReaderConfiguration configuration = new CodeReaderConfiguration(); + configuration.setBufferCapacity(10); + CodeReader reader = new CodeReader("word1 word2 word2", configuration); for (int i = 0; i < 6; i++) { reader.pop(); } |