Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Platform-independent input newline handling
Handle CR and CRLF newlines in input. Output is still hard-coded to use LF for now. MOE_MIGRATED_REVID=136407062
- Loading branch information
Showing
10 changed files
with
369 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
167 changes: 167 additions & 0 deletions
167
core/src/main/java/com/google/googlejavaformat/Newlines.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
/* | ||
* Copyright 2016 Google Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except | ||
* in compliance with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License | ||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | ||
* or implied. See the License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
|
||
package com.google.googlejavaformat; | ||
|
||
import com.google.common.base.CharMatcher; | ||
import com.google.common.collect.ImmutableSet; | ||
import com.google.common.collect.Iterators; | ||
import java.util.Iterator; | ||
import java.util.NoSuchElementException; | ||
|
||
/** Platform-independent newline handling. */ | ||
public class Newlines { | ||
|
||
/** Returns the number of line breaks in the input. */ | ||
public static int count(String input) { | ||
return Iterators.size(lineOffsetIterator(input)) - 1; | ||
} | ||
|
||
/** Returns the index of the first break in the input, or {@code -1}. */ | ||
public static int firstBreak(String input) { | ||
Iterator<Integer> it = lineOffsetIterator(input); | ||
it.next(); | ||
return it.hasNext() ? it.next() : -1; | ||
} | ||
|
||
private static final ImmutableSet<String> BREAKS = ImmutableSet.of("\r\n", "\n", "\r"); | ||
|
||
/** Returns true if the entire input string is a recognized line break. */ | ||
public static boolean isNewline(String input) { | ||
return BREAKS.contains(input); | ||
} | ||
|
||
/** | ||
* Returns the terminating line break in the input, or {@code null} if the input does not end in a | ||
* break. | ||
*/ | ||
public static String getLineEnding(String input) { | ||
for (String b : BREAKS) { | ||
if (input.endsWith(b)) { | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
cushon
Author
Collaborator
|
||
return b; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
/** Returns true if the input contains any line breaks. */ | ||
public static boolean containsBreaks(String text) { | ||
return CharMatcher.anyOf("\n\r").matchesAnyOf(text); | ||
} | ||
|
||
/** Returns an iterator over the start offsets of lines in the input. */ | ||
public static Iterator<Integer> lineOffsetIterator(String input) { | ||
return new LineOffsetIterator(input); | ||
} | ||
|
||
/** Returns an iterator over lines in the input, including trailing whitespace. */ | ||
public static Iterator<String> lineIterator(String input) { | ||
return new LineIterator(input); | ||
} | ||
|
||
private static class LineOffsetIterator implements Iterator<Integer> { | ||
|
||
private int curr = 0; | ||
private int idx = 0; | ||
private final String input; | ||
|
||
private LineOffsetIterator(String input) { | ||
this.input = input; | ||
} | ||
|
||
@Override | ||
public boolean hasNext() { | ||
return curr != -1; | ||
} | ||
|
||
@Override | ||
public Integer next() { | ||
if (curr == -1) { | ||
throw new NoSuchElementException(); | ||
} | ||
int result = curr; | ||
advance(); | ||
return result; | ||
} | ||
|
||
private void advance() { | ||
for (; idx < input.length(); idx++) { | ||
char c = input.charAt(idx); | ||
switch (c) { | ||
case '\r': | ||
if (idx + 1 < input.length() && input.charAt(idx + 1) == '\n') { | ||
idx++; | ||
} | ||
// falls through | ||
case '\n': | ||
idx++; | ||
curr = idx; | ||
return; | ||
default: | ||
break; | ||
} | ||
} | ||
curr = -1; | ||
} | ||
|
||
@Override | ||
public void remove() { | ||
throw new UnsupportedOperationException("remove"); | ||
} | ||
} | ||
|
||
private static class LineIterator implements Iterator<String> { | ||
|
||
int idx; | ||
String curr; | ||
|
||
private final String input; | ||
private final Iterator<Integer> indices; | ||
|
||
private LineIterator(String input) { | ||
this.input = input; | ||
this.indices = lineOffsetIterator(input); | ||
idx = indices.next(); // read leading 0 | ||
} | ||
|
||
private void advance() { | ||
int last = idx; | ||
if (indices.hasNext()) { | ||
idx = indices.next(); | ||
} else if (hasNext()) { | ||
// no terminal line break | ||
idx = input.length(); | ||
} else { | ||
throw new NoSuchElementException(); | ||
} | ||
curr = input.substring(last, idx); | ||
} | ||
|
||
@Override | ||
public boolean hasNext() { | ||
return idx < input.length(); | ||
} | ||
|
||
@Override | ||
public String next() { | ||
advance(); | ||
return curr; | ||
} | ||
|
||
@Override | ||
public void remove() { | ||
throw new UnsupportedOperationException("remove"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
This method fails to recognize the line ending of a text, that does not end with a line separator. Like
core\src\test\resources\com\google\googlejavaformat\java\testdata\B18479811.input