[fidl] Fix bad indentation in the absence of method ordinals.

The formatter was unable to track the beginning of a method declaration
if there was no method ordinal present.  It therefore did not know how
to indent the next line.

FIDL-395 #done

Test: Added a test to badformat.fidl.noformat
Change-Id: I68a077ed15bc4179a65a2c7ccf672ef4767aee47
diff --git a/system/host/fidl/include/fidl/formatter.h b/system/host/fidl/include/fidl/formatter.h
index c786b19..c8049e9 100644
--- a/system/host/fidl/include/fidl/formatter.h
+++ b/system/host/fidl/include/fidl/formatter.h
@@ -115,6 +115,7 @@
         OnBlankLineRespectingNode();
         ScopedBool before(blank_space_before_colon_, false);
         ScopedBool mem(is_member_decl_);
+        ScopedBool has_ordinal(has_ordinal_, element->ordinal != nullptr);
         TreeVisitor::OnInterfaceMethod(element);
     }
 
@@ -372,6 +373,9 @@
 
     bool is_member_decl_ = false;
 
+    // Does the current member have an explicit ordinal?
+    bool has_ordinal_ = false;
+
     // str is a gap plus the next meaningful token.
     void TrackInterfaceMethodAlignment(const std::string& str);
 
diff --git a/system/host/fidl/lib/formatter.cpp b/system/host/fidl/lib/formatter.cpp
index ff081c2..43b536b 100644
--- a/system/host/fidl/lib/formatter.cpp
+++ b/system/host/fidl/lib/formatter.cpp
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // The implementation for the FormattingTreeVisitor that pretty-prints FIDL code.
-
+#include <locale>
 #include <map>
 #include <regex>
 #include <set>
@@ -324,6 +324,7 @@
 //  - If there is a parameter on the same line after the '(' character,
 //    align at the same vertical column as that parameter.
 void FormattingTreeVisitor::TrackInterfaceMethodAlignment(const std::string& str) {
+    static std::locale c_locale("C");
     if (interface_method_alignment_) {
         for (int i = 0; i < str.size(); i++) {
             MaybeWindPastComment(str, i);
@@ -351,20 +352,32 @@
                 }
             }
 
-            // This tracks the distance from the beginning of the method name,
-            // in case we need it (i.e., in case we don't indent to the '('
-            // character.
-            if (!isspace(ch) && next_nonws_char_is_checkpoint_) {
-                offset_of_first_id_ =
-                    interface_method_alignment_size_ =
-                        distance_from_last_newline_ + kIndentSpaces - 1;
-                next_nonws_char_is_checkpoint_ = false;
-            }
-            if (str[i] == ':' && interface_method_alignment_size_ == -1) {
-                // The first ':' we see - means it is the gap after the ordinal.
-                // The next thing we see is the method name, so that might
-                // become the indentation level.
-                next_nonws_char_is_checkpoint_ = true;
+            if (!has_ordinal_) {
+                if (isalpha(ch, c_locale) &&
+                    interface_method_alignment_size_ == -1) {
+                    // This should be the method identifier.
+                    offset_of_first_id_ =
+                        interface_method_alignment_size_ =
+                            distance_from_last_newline_ + kIndentSpaces - 1;
+                }
+            } else {
+                // TODO(FIDL-372): remove this branch.  It is only relevant when
+                // there are explicit ordinals.
+                // This tracks the distance from the beginning of the method
+                // name, in case we need it (i.e., in case we don't indent to
+                // the '(' character.
+                if (!isspace(ch) && next_nonws_char_is_checkpoint_) {
+                    offset_of_first_id_ =
+                        interface_method_alignment_size_ =
+                            distance_from_last_newline_ + kIndentSpaces - 1;
+                    next_nonws_char_is_checkpoint_ = false;
+                }
+                if (str[i] == ':' && interface_method_alignment_size_ == -1) {
+                    // The first ':' we see - means it is the gap after the
+                    // ordinal.  The next thing we see is the method name, so
+                    // that might become the indentation level.
+                    next_nonws_char_is_checkpoint_ = true;
+                }
             }
         }
     }
diff --git a/system/utest/fidl-compiler/testdata/badformat.fidl.noformat b/system/utest/fidl-compiler/testdata/badformat.fidl.noformat
index 8691a28..3c8ddda 100644
--- a/system/utest/fidl-compiler/testdata/badformat.fidl.noformat
+++ b/system/utest/fidl-compiler/testdata/badformat.fidl.noformat
@@ -70,6 +70,9 @@
     104: Nimon(int32 j, string k     )
         -> ( int32 y );
 
+    Mandrel(int32 j, string k     )
+        -> ( int32 y );
+
     6: Cat(string? s) -> (bool b);  102: Karfel(
     int32 x) -> (int y);
 
diff --git a/system/utest/fidl-compiler/testdata/goodformat.fidl b/system/utest/fidl-compiler/testdata/goodformat.fidl
index ed14727..a33a18c 100644
--- a/system/utest/fidl-compiler/testdata/goodformat.fidl
+++ b/system/utest/fidl-compiler/testdata/goodformat.fidl
@@ -75,6 +75,9 @@
     104: Nimon(int32 j, string k)
              -> (int32 y);
 
+    Mandrel(int32 j, string k)
+        -> (int32 y);
+
     6: Cat(string? s) -> (bool b);
     102: Karfel(
              int32 x) -> (int y);