Skip to content

Commit

Permalink
Don't mangle non-javadoc block comments
Browse files Browse the repository at this point in the history
Previously leading whitespace was being removed from non-javadoc block
comments, which destroyed existing formatting. This change preserves the
relative indentation of those block comments.

Also: for javadoc and block comments with leading '*'s, add missing '*'s while
re-indenting.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=105236622
  • Loading branch information
cushon committed Oct 14, 2015
1 parent dd4aa31 commit 312ed57
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 12 deletions.
10 changes: 10 additions & 0 deletions core/src/main/java/com/google/googlejavaformat/Doc.java
Expand Up @@ -14,6 +14,7 @@


package com.google.googlejavaformat; package com.google.googlejavaformat;


import com.google.common.base.CharMatcher;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.collect.DiscreteDomain; import com.google.common.collect.DiscreteDomain;
Expand Down Expand Up @@ -747,6 +748,15 @@ public void add(DocBuilder builder) {


@Override @Override
float computeWidth() { float computeWidth() {
// only count the first line of multi-line block comments
if (tok.isComment()) {
int idx = tok.getOriginalText().indexOf('\n');
if (idx > 0) {
return idx;
} else {
return tok.getOriginalText().length();
}
}
return tok.getOriginalText().contains("\n") return tok.getOriginalText().contains("\n")
? Float.POSITIVE_INFINITY ? Float.POSITIVE_INFINITY
: (float) tok.getOriginalText().length(); : (float) tok.getOriginalText().length();
Expand Down
Expand Up @@ -14,33 +14,121 @@


package com.google.googlejavaformat.java; package com.google.googlejavaformat.java;


import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.googlejavaformat.CommentsHelper; import com.google.googlejavaformat.CommentsHelper;
import com.google.googlejavaformat.Input; import com.google.googlejavaformat.Input;
import com.google.googlejavaformat.Input.Tok;


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;


/** {@code JavaCommentsHelper} extends {@link CommentsHelper} to rewrite Java comments. */ /** {@code JavaCommentsHelper} extends {@link CommentsHelper} to rewrite Java comments. */
public final class JavaCommentsHelper implements CommentsHelper { public final class JavaCommentsHelper implements CommentsHelper {
private static final Splitter NEWLINE_SPLITTER = Splitter.on('\n').trimResults(); private static final Splitter NEWLINE_SPLITTER = Splitter.on('\n');


@Override @Override
public String rewrite(Input.Tok tok, int maxWidth, int column0) { public String rewrite(Tok tok, int maxWidth, int column0) {
List<String> rawLines = NEWLINE_SPLITTER.splitToList(tok.getOriginalText()); if (!tok.isComment()) {
return tok.getOriginalText();
}
ArrayList<String> lines = new ArrayList<>();
for (String line : NEWLINE_SPLITTER.splitToList(tok.getOriginalText())) {
lines.add(CharMatcher.WHITESPACE.trimTrailingFrom(line));
}
if (lines.size() == 1) {
return tok.getOriginalText().trim();
}
if (tok.isSlashSlashComment()) {
return indentLineComments(lines, column0);
} else if (javadocShaped(lines)) {
return indentJavadoc(lines, column0);
} else {
return preserveIndentation(lines, column0);
}
}

// For non-javadoc-shaped block comments, shift the entire block to the correct
// column, but do not adjust relative indentation.
private static String preserveIndentation(List<String> lines, int column0) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
String firstLine = rawLines.get(0);
builder.append(firstLine); // find the leftmost non-whitespace character in all trailing lines
int indent = column0; int startCol = -1;
if (firstLine.startsWith("/*")) { for (int i = 1; i < lines.size(); i++) {
// For block and javadoc comments, add an extra space to trailing lines int lineIdx = CharMatcher.WHITESPACE.negate().indexIn(lines.get(i));
// to align the "*" at the beginning of each line with the first "/*". if (lineIdx >= 0 && (startCol == -1 || lineIdx < startCol)) {
indent++; startCol = lineIdx;
}
} }

// output the first line at the current column
builder.append(lines.get(0));

// output all trailing lines with plausible indentation
for (int i = 1; i < lines.size(); ++i) {
builder.append("\n").append(Strings.repeat(" ", column0));
// check that startCol is valid index, e.g. for blank lines
if (lines.get(i).length() >= startCol) {
builder.append(lines.get(i).substring(startCol));
} else {
builder.append(lines.get(i));
}
}
return builder.toString();
}

// Remove leading and trailing whitespace, and re-indent each line.
private static String indentLineComments(List<String> lines, int column0) {
StringBuilder builder = new StringBuilder();
builder.append(lines.get(0).trim());
String indentString = Strings.repeat(" ", column0);
for (int i = 1; i < lines.size(); ++i) {
builder.append("\n").append(indentString).append(lines.get(i).trim());
}
return builder.toString();
}

// Remove leading and trailing whitespace, and re-indent each line.
// Add a +1 indent before '*', and add the '*' if necessary.
private static String indentJavadoc(List<String> lines, int column0) {
StringBuilder builder = new StringBuilder();
builder.append(lines.get(0).trim());
int indent = column0 + 1;
String indentString = Strings.repeat(" ", indent); String indentString = Strings.repeat(" ", indent);
for (int i = 1; i < rawLines.size(); ++i) { for (int i = 1; i < lines.size(); ++i) {
builder.append("\n").append(indentString).append(rawLines.get(i)); builder.append("\n").append(indentString);
String line = lines.get(i).trim();
if (!line.startsWith("*")) {
builder.append("* ");
}
builder.append(line);
} }
return builder.toString(); return builder.toString();
} }

// Returns true if the comment looks like javadoc
private static boolean javadocShaped(List<String> lines) {
Iterator<String> it = lines.iterator();
if (!it.hasNext()) {
return false;
}
String first = it.next().trim();
// if it's actually javadoc, we're done
if (first.startsWith("/**")) {
return true;
}
// if it's a block comment, check all trailing lines for '*'
if (!first.startsWith("/*")) {
return false;
}
while (it.hasNext()) {
if (!it.next().trim().startsWith("*")) {
return false;
}
}
return true;
}
} }
@@ -0,0 +1,76 @@
/**
* This<br>
* is<br>
* a<br>
* train.
*/
class TheTrain {
/*
______
.-"""".._'. _,##
_..__ |.-"""-.| | _,##'`-._
(_____)||_____|| |_,##'`-._,##'`
_| |.;-""-. | |#'`-._,##'`
_.;_ `--' `\ \ |.'`\._,##'`
/.-.\ `\ |.-";.`_, |##'`
|\__/ | _..;__ |'-' /
'.____.'_.-`)\--' /'-'`
//||\\(_.-'_,'-'`
(`-...-')_,##'`
jgs _,##`-..,-;##`
_,##'`-._,##'`
_,##'`-._,##'`
`-._,##'`
*/
public static final Object THE_TRAIN = null;

/*
BLOCK COMMENT

*/
int x;

/* .
BLOCK COMMENT .

*/
int y;

/* .
BLOCK COMMENT .

*/
int z;

/* .
BLOCK COMMENT .

*/
int z;

/*
* This is almost javadoc.
*
*/
int z;

/**
* This is (was) malformed javadoc.
* <pre>
System.err.println
* </pre>
*/
int z;

private Object f; /*-{
System.err.println("asd");
}-*/

private native Object f() /*-{
System.err.println("asd");
}-*/;

private native Object f() /*-{
System.err.println("asd");
}-*/;
}
@@ -0,0 +1,76 @@
/**
* This<br>
* is<br>
* a<br>
* train.
*/
class TheTrain {
/*
______
.-"""".._'. _,##
_..__ |.-"""-.| | _,##'`-._
(_____)||_____|| |_,##'`-._,##'`
_| |.;-""-. | |#'`-._,##'`
_.;_ `--' `\ \ |.'`\._,##'`
/.-.\ `\ |.-";.`_, |##'`
|\__/ | _..;__ |'-' /
'.____.'_.-`)\--' /'-'`
//||\\(_.-'_,'-'`
(`-...-')_,##'`
jgs _,##`-..,-;##`
_,##'`-._,##'`
_,##'`-._,##'`
`-._,##'`
*/
public static final Object THE_TRAIN = null;

/*
BLOCK COMMENT

*/
int x;

/* .
BLOCK COMMENT .

*/
int y;

/* .
BLOCK COMMENT .

*/
int z;

/* .
BLOCK COMMENT .

*/
int z;

/*
* This is almost javadoc.
*
*/
int z;

/**
* This is (was) malformed javadoc.
* <pre>
* System.err.println
* </pre>
*/
int z;

private Object f; /*-{
System.err.println("asd");
}-*/

private native Object f() /*-{
System.err.println("asd");
}-*/;

private native Object f() /*-{
System.err.println("asd");
}-*/;
}

0 comments on commit 312ed57

Please sign in to comment.