diff options
author | Dinesh Bolkensteyn <dinesh@dinsoft.net> | 2011-10-20 20:50:42 +0200 |
---|---|---|
committer | Dinesh Bolkensteyn <dinesh@dinsoft.net> | 2011-10-20 20:51:35 +0200 |
commit | 0b9c56c76952cc93dea74b386938154158f407dd (patch) | |
tree | 2f64114c3f62beb436ba9072cc0e852aa2483974 /sonar-channel | |
parent | 58f71c9c265323a5c341e365816521a7119eae07 (diff) | |
download | sonarqube-0b9c56c76952cc93dea74b386938154158f407dd.tar.gz sonarqube-0b9c56c76952cc93dea74b386938154158f407dd.zip |
SONAR-2923 and SONAR-2632: Remove sonar-channel buffer restriction and character pushback feature
Diffstat (limited to 'sonar-channel')
6 files changed, 56 insertions, 137 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 5422def73a3..032f2d67ef6 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java +++ b/sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java @@ -73,6 +73,7 @@ public final class ChannelCodeReaderFilter<OUTPUT> extends CodeReaderFilter<OUTP */ @Override public int read(char[] filteredBuffer, int offset, int length) throws IOException { + if (internalCodeReader.peek() == -1) return -1; int initialOffset = offset; while (offset < filteredBuffer.length) { if (internalCodeReader.peek() == -1) { 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 7274181662e..5a4e1a668e0 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java +++ b/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java @@ -23,6 +23,7 @@ import java.io.FilterReader; import java.io.IOException; import java.io.Reader; import java.io.StringReader; +import java.nio.CharBuffer; import org.apache.commons.io.IOUtils; @@ -38,13 +39,10 @@ import org.apache.commons.io.IOUtils; */ public class CodeBuffer implements CharSequence { - private final Reader code; private int lastChar = -1; private Cursor cursor; - 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; @@ -52,22 +50,41 @@ public class CodeBuffer implements CharSequence { private boolean recordingMode = false; private StringBuilder recordedCharacters = new StringBuilder(); + protected CodeBuffer(String code, CodeReaderConfiguration configuration) { + this(new StringReader(code), configuration); + } + protected CodeBuffer(Reader initialCodeReader, CodeReaderConfiguration configuration) { lastChar = -1; cursor = new Cursor(); - bufferCapacity = configuration.getBufferCapacity(); tabWidth = configuration.getTabWidth(); - buffer = new char[bufferCapacity]; + + /* Setup the filters on the reader */ Reader reader = initialCodeReader; for (CodeReaderFilter<?> codeReaderFilter : configuration.getCodeReaderFilters()) { reader = new Filter(reader, codeReaderFilter, configuration); } - this.code = reader; - fillBuffer(); + + /* Buffer the whole reader */ + fillBuffer(reader); + + /* Clean-up */ + IOUtils.closeQuietly(reader); } - - protected CodeBuffer(String code, CodeReaderConfiguration configuration) { - this(new StringReader(code), configuration); + + private void fillBuffer(Reader reader) { + try { + StringBuilder sb = new StringBuilder(); + char[] buffer = new char[4096]; + int read; + while ((read = reader.read(buffer)) != -1) { + sb.append(buffer, 0, read); + } + this.buffer = new char[sb.length()]; + sb.getChars(0, sb.length(), this.buffer, 0); + } catch (IOException e) { + throw new RuntimeException(e); + } } /** @@ -76,16 +93,13 @@ public class CodeBuffer implements CharSequence { * @return the next character or -1 if the end of the stream is reached */ public final int pop() { - if (bufferPosition == bufferSize) { - fillBuffer(); - } - if (bufferSize == 0) { + if (bufferPosition >= buffer.length) { return -1; } int character = buffer[bufferPosition++]; updateCursorPosition(character); if (recordingMode) { - recordedCharacters.append((char) character); + recordedCharacters.append((char)character); } lastChar = character; return character; @@ -103,24 +117,6 @@ public class CodeBuffer implements CharSequence { } } - private int fillBuffer() { - try { - int offset = bufferSize - bufferPosition; - if (offset != 0) { - System.arraycopy(buffer, bufferPosition, buffer, 0, bufferSize - bufferPosition); - } - bufferPosition = 0; - int numberOfChars = code.read(buffer, offset, bufferCapacity - offset); - if (numberOfChars == -1) { - numberOfChars = 0; - } - bufferSize = numberOfChars + offset; - return offset; - } catch (IOException e) { - throw new ChannelException(e.getMessage(), e); - } - } - /** * Looks at the last consumed character * @@ -140,38 +136,6 @@ public class CodeBuffer implements CharSequence { } /** - * Pushes a character sequence onto the top of this CodeBuffer. This characters will be then the first to be read. - * - * @param chars - * the character sequences to push into the CodeBuffer - */ - public void push(CharSequence chars) { - int length = chars.length(); - if (bufferPosition >= length) { - for (int index = 0; index < length; index++) { - buffer[bufferPosition + index - length] = chars.charAt(index); - } - bufferPosition -= length; - } else { - char[] extendedBuffer = new char[buffer.length - bufferPosition + length]; - for (int index = 0; index < length; index++) { - extendedBuffer[index] = chars.charAt(index); - } - System.arraycopy(buffer, bufferPosition, extendedBuffer, length, bufferSize - bufferPosition); - buffer = extendedBuffer; - bufferSize = bufferSize + length - bufferPosition; - bufferPosition = 0; - } - } - - /** - * Close the stream - */ - public final void close() { - IOUtils.closeQuietly(code); - } - - /** * @return the current line of the cursor */ public final int getLinePosition() { @@ -219,33 +183,26 @@ public class CodeBuffer implements CharSequence { * Returns the character at the specified index after the cursor without consuming it * * @param index - * the index of the character to be returned + * the relative index of the character to be returned * @return the desired character * @see java.lang.CharSequence#charAt(int) */ public final char charAt(int index) { - return (char) intAt(index); + return (char)intAt(index); } protected final int intAt(int index) { - if (bufferPosition + index > bufferSize - 1) { - fillBuffer(); - } - if (bufferPosition + index > bufferSize - 1) { + if (bufferPosition + index >= buffer.length) { return -1; } return buffer[bufferPosition + index]; } /** - * Warning : this method returns Integer.MAX_VALUE when the buffer is fully used - * as the length of the stream can't be known before having consumed all characters. - * - * Integer.MAX_VALUE is returned to prevent regular expression matchers to stop consuming the stream of characters (see - * http://jira.codehaus.org/browse/SONAR-2010) + * Returns the relative length of the string (i.e. excluding the popped chars) */ public final int length() { - return (bufferSize == bufferCapacity ? Integer.MAX_VALUE : bufferSize - bufferPosition); + return buffer.length - bufferPosition; } public final CharSequence subSequence(int start, int end) { diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java b/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java index bd543207ea9..7347074b01d 100644 --- a/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java +++ b/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java @@ -28,32 +28,13 @@ import java.util.List; */ public class CodeReaderConfiguration { - public final static int DEFAULT_BUFFER_CAPACITY = 8000; - public final static int DEFAULT_TAB_WIDTH = 1; - private int bufferCapacity = DEFAULT_BUFFER_CAPACITY; - private int tabWidth = DEFAULT_TAB_WIDTH; private List<CodeReaderFilter<?>> codeReaderFilters = new ArrayList<CodeReaderFilter<?>>(); /** - * @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() { @@ -96,7 +77,6 @@ public class CodeReaderConfiguration { public CodeReaderConfiguration cloneWithoutCodeReaderFilters() { CodeReaderConfiguration clone = new CodeReaderConfiguration(); - clone.setBufferCapacity(bufferCapacity); clone.setTabWidth(tabWidth); return clone; } 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 471b16bd975..387978fe069 100644 --- a/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java +++ b/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java @@ -117,20 +117,6 @@ public class CodeBufferTest { } @Test - public void testPush() { - CodeReader reader = new CodeReader("12", defaulConfiguration); - assertEquals('1', (char) reader.pop()); - reader.push("a"); - assertEquals('a', (char) reader.peek()); - reader.push("45"); - assertEquals("45a2", new String(reader.peek(4))); - for (int i = 0; i < 4; i++) { - reader.pop(); - } - assertEquals( -1, reader.pop()); - } - - @Test public void testCharAtIndexOutOfBoundsException() { CodeBuffer reader = new CodeBuffer("12345", defaulConfiguration); assertEquals(reader.charAt(5), (char) -1); @@ -210,14 +196,6 @@ public class CodeBufferTest { } @Test - public void theLengthShouldBeIntegerMaxValueWhenTheBufferCantContainAllCharacters() { - String myCode = "myCode"; - CodeReaderConfiguration conf = new CodeReaderConfiguration(); - conf.setBufferCapacity(2); - assertThat(new CodeBuffer(myCode, conf).length(), is(Integer.MAX_VALUE)); - } - - @Test public void testSeveralCodeReaderFilter() throws Exception { CodeReaderConfiguration configuration = new CodeReaderConfiguration(); configuration.setCodeReaderFilters(new ReplaceNumbersFilter(), new ReplaceCharFilter()); 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 a748cfa6f83..b6f1d0b8289 100644 --- a/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java +++ b/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java @@ -84,24 +84,6 @@ public class CodeReaderTest { } @Test - public void testPeekToAndReachingTheBufferLimit() { - CodeReaderConfiguration configuration = new CodeReaderConfiguration(); - configuration.setBufferCapacity(10); - CodeReader reader = new CodeReader("word1 word2 word2", configuration); - for (int i = 0; i < 6; i++) { - reader.pop(); - } - StringBuilder result = new StringBuilder(); - reader.peekTo(new EndMatcher() { - - public boolean match(int endFlag) { - return ' ' == (char) endFlag; - } - }, result); - assertEquals("word2", result.toString()); - } - - @Test public void testPopToWithRegex() { CodeReader reader = new CodeReader(new StringReader("123ABC")); StringBuilder token = new StringBuilder(); diff --git a/sonar-channel/src/test/java/org/sonar/channel/RegexChannelTest.java b/sonar-channel/src/test/java/org/sonar/channel/RegexChannelTest.java index 35d9c936b78..322899266ab 100644 --- a/sonar-channel/src/test/java/org/sonar/channel/RegexChannelTest.java +++ b/sonar-channel/src/test/java/org/sonar/channel/RegexChannelTest.java @@ -33,7 +33,28 @@ public class RegexChannelTest { dispatcher.consume(new CodeReader("my word"), output); assertThat(output.toString(), is("<w>my</w> <w>word</w>")); } + + @Test + public void shouldMatchTokenLongerThanBuffer() { + ChannelDispatcher<StringBuilder> dispatcher = ChannelDispatcher.builder().addChannel(new MyLiteralChannel()).build(); + StringBuilder output = new StringBuilder(); + + dispatcher.consume(new CodeReader("\"bonjour\""), output); + assertThat(output.toString(), is("<literal>\"bonjour\"</literal>")); + } + + private static class MyLiteralChannel extends RegexChannel<StringBuilder> { + + public MyLiteralChannel() { + super("\"[^\"]*+\""); + } + @Override + protected void consume(CharSequence token, StringBuilder output) { + output.append("<literal>" + token + "</literal>"); + } + } + private static class MyWordChannel extends RegexChannel<StringBuilder> { public MyWordChannel() { |