Handle Javadoc MOE directives specially.

MOE_MIGRATED_REVID=124762545
diff --git a/core/src/main/java/com/google/googlejavaformat/java/javadoc/GoogleJavadocFormatter.java b/core/src/main/java/com/google/googlejavaformat/java/javadoc/GoogleJavadocFormatter.java
index 90af5cd..ddf998e 100644
--- a/core/src/main/java/com/google/googlejavaformat/java/javadoc/GoogleJavadocFormatter.java
+++ b/core/src/main/java/com/google/googlejavaformat/java/javadoc/GoogleJavadocFormatter.java
@@ -92,6 +92,12 @@
         case TABLE_CLOSE_TAG:
           output.writeTableClose(token);
           break;
+        case MOE_BEGIN_STRIP_COMMENT:
+          output.requestMoeBeginStripComment(token);
+          break;
+        case MOE_END_STRIP_COMMENT:
+          output.writeMoeEndStripComment(token);
+          break;
         case HTML_COMMENT:
           output.writeHtmlComment(token);
           break;
diff --git a/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocLexer.java b/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocLexer.java
index e599ec4..ffebd4e 100644
--- a/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocLexer.java
+++ b/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocLexer.java
@@ -33,6 +33,8 @@
 import static com.google.googlejavaformat.java.javadoc.Token.Type.LIST_ITEM_OPEN_TAG;
 import static com.google.googlejavaformat.java.javadoc.Token.Type.LIST_OPEN_TAG;
 import static com.google.googlejavaformat.java.javadoc.Token.Type.LITERAL;
+import static com.google.googlejavaformat.java.javadoc.Token.Type.MOE_BEGIN_STRIP_COMMENT;
+import static com.google.googlejavaformat.java.javadoc.Token.Type.MOE_END_STRIP_COMMENT;
 import static com.google.googlejavaformat.java.javadoc.Token.Type.PARAGRAPH_CLOSE_TAG;
 import static com.google.googlejavaformat.java.javadoc.Token.Type.PARAGRAPH_OPEN_TAG;
 import static com.google.googlejavaformat.java.javadoc.Token.Type.PRE_CLOSE_TAG;
@@ -189,6 +191,10 @@
       return HEADER_CLOSE_TAG;
     } else if (input.tryConsumeRegex(BR_PATTERN)) {
       return BR_TAG;
+    } else if (input.tryConsumeRegex(MOE_BEGIN_STRIP_COMMENT_PATTERN)) {
+      return MOE_BEGIN_STRIP_COMMENT;
+    } else if (input.tryConsumeRegex(MOE_END_STRIP_COMMENT_PATTERN)) {
+      return MOE_END_STRIP_COMMENT;
     } else if (input.tryConsumeRegex(HTML_COMMENT_PATTERN)) {
       return HTML_COMMENT;
     } else if (input.tryConsumeRegex(LITERAL_PATTERN)) {
@@ -272,6 +278,10 @@
   private static final Pattern NEWLINE_PATTERN = compile("^[ \t]*\n[ \t]*[*]?[ \t]?");
   // We ensure elsewhere that we match this only at the beginning of a line.
   private static final Pattern FOOTER_TAG_PATTERN = compile("^@\\w*");
+  private static final Pattern MOE_BEGIN_STRIP_COMMENT_PATTERN =
+      compile("^<!--\\s*MOE:begin_intracomment_strip\\s*-->");
+  private static final Pattern MOE_END_STRIP_COMMENT_PATTERN =
+      compile("^<!--\\s*MOE:end_intracomment_strip\\s*-->");
   private static final Pattern HTML_COMMENT_PATTERN = fullCommentPattern();
   private static final Pattern PRE_OPEN_PATTERN = openTagPattern("pre");
   private static final Pattern PRE_CLOSE_PATTERN = closeTagPattern("pre");
diff --git a/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java b/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java
index 086e14c..8051d8f 100644
--- a/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java
+++ b/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java
@@ -54,6 +54,8 @@
   private int remainingOnLine;
   private boolean atStartOfLine;
   private RequestedWhitespace requestedWhitespace = NONE;
+  private Token requestedMoeBeginStripComment;
+  private int indentForMoeEndStripComment;
   private boolean wroteAnythingSignificant;
 
   JavadocWriter(int blockIndent, JavaFormatterOptions options) {
@@ -70,6 +72,11 @@
     requestWhitespace(WHITESPACE);
   }
 
+  void requestMoeBeginStripComment(Token token) {
+    // We queue this up so that we can put it after any requested whitespace.
+    requestedMoeBeginStripComment = checkNotNull(token);
+  }
+
   void writeBeginJavadoc() {
     /*
      * JavaCommentsHelper will make sure this is indented right. But it seems sensible enough that,
@@ -199,6 +206,16 @@
     requestBlankLine();
   }
 
+  void writeMoeEndStripComment(Token token) {
+    writeLineBreakNoAutoIndent();
+    appendSpaces(indentForMoeEndStripComment);
+
+    // Or maybe just "output.append(token.getValue())?" I'm kind of surprised this is so easy.
+    writeToken(token);
+
+    requestNewline();
+  }
+
   void writeHtmlComment(Token token) {
     requestNewline();
 
@@ -254,6 +271,10 @@
   }
 
   private void writeToken(Token token) {
+    if (requestedMoeBeginStripComment != null) {
+      requestNewline();
+    }
+
     if (requestedWhitespace == BLANK_LINE && (continuingListItemCount > 0 || continuingFooterTag)) {
       /*
        * We don't write blank lines inside lists or footer tags, even in cases where we otherwise
@@ -287,6 +308,15 @@
       remainingOnLine--;
     }
 
+    if (requestedMoeBeginStripComment != null) {
+      output.append(requestedMoeBeginStripComment.getValue());
+      requestedMoeBeginStripComment = null;
+      indentForMoeEndStripComment = innerIndent();
+      requestNewline();
+      writeToken(token);
+      return;
+    }
+
     output.append(token.getValue());
 
     if (!START_OF_LINE_TOKENS.contains(token.getType())) {
diff --git a/core/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java b/core/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java
index 9828e3e..6e76698 100644
--- a/core/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java
+++ b/core/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java
@@ -56,6 +56,10 @@
     PRE_CLOSE_TAG,
     TABLE_OPEN_TAG,
     TABLE_CLOSE_TAG,
+    /** {@code <!-- MOE:begin_intracomment_strip -->} */
+    MOE_BEGIN_STRIP_COMMENT,
+    /** {@code <!-- MOE:end_intracomment_strip -->} */
+    MOE_END_STRIP_COMMENT,
     HTML_COMMENT,
     // TODO(cpovirk): Support <hr> (probably a blank line before and after).
     BR_TAG,
diff --git a/core/src/test/java/com/google/googlejavaformat/java/GoogleJavadocFormattingTest.java b/core/src/test/java/com/google/googlejavaformat/java/GoogleJavadocFormattingTest.java
index f03bb57..77b7efc 100644
--- a/core/src/test/java/com/google/googlejavaformat/java/GoogleJavadocFormattingTest.java
+++ b/core/src/test/java/com/google/googlejavaformat/java/GoogleJavadocFormattingTest.java
@@ -107,6 +107,119 @@
   }
 
   @Test
+  public void moeComments() {
+    String[] input = {
+      "/**",
+      " * Deatomizes the given user.",
+      " * <!-- MOE:begin_intracomment_strip -->",
+      " * See go/deatomizer-v5 for the design doc.",
+      " * <!-- MOE:end_intracomment_strip -->",
+      " * To reatomize, call {@link reatomize}.",
+      " *",
+      " * <!-- MOE:begin_intracomment_strip -->",
+      " * <p>This method is used in the Google teleporter.",
+      " *",
+      " * <p>Yes, we have a teleporter.",
+      " * <!-- MOE:end_intracomment_strip -->",
+      " *",
+      " * @param user the person to teleport.",
+      " *     <!-- MOE:begin_intracomment_strip -->",
+      " *     Users must sign go/deatomize-waiver ahead of time.",
+      " *     <!-- MOE:end_intracomment_strip -->",
+      " * <!-- MOE:begin_intracomment_strip -->",
+      " * @deprecated Sometimes turns the user into a goat.",
+      " * <!-- MOE:end_intracomment_strip -->",
+      " */",
+      "class Test {}",
+    };
+    String[] expected = {
+      "/**",
+      " * Deatomizes the given user.",
+      " * <!-- MOE:begin_intracomment_strip -->",
+      " * See go/deatomizer-v5 for the design doc.",
+      " * <!-- MOE:end_intracomment_strip -->",
+      " * To reatomize, call {@link reatomize}.",
+      " *",
+      " * <!-- MOE:begin_intracomment_strip -->",
+      " * <p>This method is used in the Google teleporter.",
+      " *",
+      " * <p>Yes, we have a teleporter.",
+      " * <!-- MOE:end_intracomment_strip -->",
+      " *",
+      " * @param user the person to teleport.",
+      " *     <!-- MOE:begin_intracomment_strip -->",
+      " *     Users must sign go/deatomize-waiver ahead of time.",
+      " *     <!-- MOE:end_intracomment_strip -->",
+      " * <!-- MOE:begin_intracomment_strip -->",
+      " * @deprecated Sometimes turns the user into a goat.",
+      " * <!-- MOE:end_intracomment_strip -->",
+      " */",
+      "class Test {}",
+    };
+    doFormatTest(input, expected);
+  }
+
+  @Test
+  public void moeCommentBeginOnlyInMiddleOfDoc() {
+    // We don't really care what happens here so long as we don't explode.
+    String[] input = {
+      "/**", //
+      " * Foo.",
+      " * <!-- MOE:begin_intracomment_strip -->",
+      " * Bar.",
+      " */",
+      "class Test {}",
+    };
+    String[] expected = {
+      "/**", //
+      " * Foo.",
+      " * <!-- MOE:begin_intracomment_strip -->",
+      " * Bar.",
+      " */",
+      "class Test {}",
+    };
+    doFormatTest(input, expected);
+  }
+
+  @Test
+  public void moeCommentBeginOnlyAtEndOfDoc() {
+    // We don't really care what happens here so long as we don't explode.
+    // TODO(cpovirk): OK, maybe try to leave it in....
+    String[] input = {
+      "/**", //
+      " * Foo.",
+      " * <!-- MOE:begin_intracomment_strip -->",
+      " */",
+      "class Test {}",
+    };
+    String[] expected = {
+      "/** Foo. */", //
+      "class Test {}",
+    };
+    doFormatTest(input, expected);
+  }
+
+  @Test
+  public void moeCommentEndOnly() {
+    // We don't really care what happens here so long as we don't explode.
+    String[] input = {
+      "/**", //
+      " * Foo.",
+      " * <!-- MOE:end_intracomment_strip -->",
+      " */",
+      "class Test {}",
+    };
+    String[] expected = {
+      "/**", //
+      " * Foo.",
+      " * <!-- MOE:end_intracomment_strip -->",
+      " */",
+      "class Test {}",
+    };
+    doFormatTest(input, expected);
+  }
+
+  @Test
   public void tableMostlyUntouched() {
     String[] input = {
       "/**",