com.google.googlejavaformat.Newlines Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of google-java-format Show documentation
Show all versions of google-java-format Show documentation
A Java source code formatter that follows Google Java Style.
/*
* 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 it = lineOffsetIterator(input);
it.next();
return it.hasNext() ? it.next() : -1;
}
private static final ImmutableSet 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 length of the newline sequence at the current offset, or {@code -1}. */
public static int hasNewlineAt(String input, int idx) {
for (String b : BREAKS) {
if (input.startsWith(b, idx)) {
return b.length();
}
}
return -1;
}
/**
* 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)) {
return b;
}
}
return null;
}
/**
* Returns the first line separator in the text, or {@code "\n"} if the text does not contain a
* single line separator.
*/
public static String guessLineSeparator(String text) {
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
switch (c) {
case '\r':
if (i + 1 < text.length() && text.charAt(i + 1) == '\n') {
return "\r\n";
}
return "\r";
case '\n':
return "\n";
default:
break;
}
}
return "\n";
}
/** 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 lineOffsetIterator(String input) {
return new LineOffsetIterator(input);
}
/** Returns an iterator over lines in the input, including trailing whitespace. */
public static Iterator lineIterator(String input) {
return new LineIterator(input);
}
private static class LineOffsetIterator implements Iterator {
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 {
int idx;
String curr;
private final String input;
private final Iterator 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");
}
}
}