summaryrefslogtreecommitdiffstats
path: root/sonar-channel
diff options
context:
space:
mode:
authorbellingard <bellingard@gmail.com>2010-10-21 14:09:13 +0000
committerbellingard <bellingard@gmail.com>2010-10-21 14:09:13 +0000
commita16fe9d1448070c61f8eb7d43369643b666cf71b (patch)
treefcd63f74cb06c1d08ec6aacec854d569d9e528ae /sonar-channel
parent938b174bc222412d372730d64c23117100afefaf (diff)
downloadsonarqube-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')
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java4
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/ChannelDispatcher.java6
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java27
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/CodeReader.java36
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java90
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/CodeReaderFilter.java21
-rw-r--r--sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java61
-rw-r--r--sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java6
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();
}