Apply CleanPath() before comparing paths

Paths are sometimes prefixed with "./". CleanPath() is moved from
FakeIoDelegate to IoDelegate so that Parser uses it before comparing
paths.

Ideally, we should use std::filesystem::path::lexically_normal(), but
it's not available on windows platform which we support.

Removing "./" is good enough for most cases. To be specific, this
happens when we pass "-I.".

Bug: n/a
Test: m (aidl_unittests)
Change-Id: Ied6eaf1b264102d997306ac0cc2c32934056b27c
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 0218561..81931a1 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -962,7 +962,7 @@
 
 TEST_P(AidlTest, StructuredFailOnUnstructuredParcelable) {
   const string expected_stderr =
-      "ERROR: ./o/WhoKnowsWhat.aidl:1.22-35: o.WhoKnowsWhat is not structured, but this is a "
+      "ERROR: o/WhoKnowsWhat.aidl:1.22-35: o.WhoKnowsWhat is not structured, but this is a "
       "structured interface.\n";
   io_delegate_.SetFileContents("o/WhoKnowsWhat.aidl", "package o; parcelable WhoKnowsWhat;");
   import_paths_.emplace("");
diff --git a/io_delegate.cpp b/io_delegate.cpp
index 45ef65a..c05f4b1 100644
--- a/io_delegate.cpp
+++ b/io_delegate.cpp
@@ -43,6 +43,7 @@
 using android::base::Error;
 using android::base::Result;
 using android::base::Split;
+using android::base::StartsWith;
 
 namespace android {
 namespace aidl {
@@ -244,5 +245,12 @@
 }
 #endif
 
+string IoDelegate::CleanPath(const string& path) {
+  if (base::StartsWith(path, string{'.', OS_PATH_SEPARATOR})) {
+    return path.substr(2);
+  }
+  return path;
+}
+
 }  // namespace android
 }  // namespace aidl
diff --git a/io_delegate.h b/io_delegate.h
index 6c1ef96..e0b7252 100644
--- a/io_delegate.h
+++ b/io_delegate.h
@@ -44,6 +44,9 @@
   static bool GetAbsolutePath(const std::string& path,
                               std::string* absolute_path);
 
+  // Remove leading "./" from |path|.
+  static std::string CleanPath(const std::string& path);
+
   // Returns a unique_ptr to the contents of |filename|.
   // Will append the optional |content_suffix| to the returned contents.
   virtual std::unique_ptr<std::string> GetFileContents(
diff --git a/parser.cpp b/parser.cpp
index 93770bb..abe1dbf 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -28,16 +28,17 @@
 const AidlDocument* Parser::Parse(const std::string& filename,
                                   const android::aidl::IoDelegate& io_delegate,
                                   AidlTypenames& typenames) {
+  auto clean_path = android::aidl::IoDelegate::CleanPath(filename);
   // reuse pre-parsed document from typenames
   for (auto& doc : typenames.AllDocuments()) {
-    if (doc->GetLocation().GetFile() == filename) {
+    if (doc->GetLocation().GetFile() == clean_path) {
       return doc.get();
     }
   }
   // Make sure we can read the file first, before trashing previous state.
-  unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
+  unique_ptr<string> raw_buffer = io_delegate.GetFileContents(clean_path);
   if (raw_buffer == nullptr) {
-    AIDL_ERROR(filename) << "Error while opening file for parsing";
+    AIDL_ERROR(clean_path) << "Error while opening file for parsing";
     return nullptr;
   }
 
@@ -45,7 +46,7 @@
   // nulls at the end.
   raw_buffer->append(2u, '\0');
 
-  Parser parser(filename, *raw_buffer, typenames);
+  Parser parser(clean_path, *raw_buffer, typenames);
 
   if (yy::parser(&parser).parse() != 0 || parser.HasError()) {
     return nullptr;
diff --git a/tests/fake_io_delegate.cpp b/tests/fake_io_delegate.cpp
index a99a20a..5e912ce 100644
--- a/tests/fake_io_delegate.cpp
+++ b/tests/fake_io_delegate.cpp
@@ -167,16 +167,6 @@
   return false;
 }
 
-string FakeIoDelegate::CleanPath(const string& path) const {
-  string clean_path = path;
-  while (clean_path.length() >= 2 &&
-         clean_path[0] == '.' &&
-         clean_path[1] == OS_PATH_SEPARATOR) {
-    clean_path = clean_path.substr(2);
-  }
-  return clean_path;
-}
-
 }  // namespace test
 }  // namespace aidl
 }  // namespace android
diff --git a/tests/fake_io_delegate.h b/tests/fake_io_delegate.h
index 6f24678..0e278f4 100644
--- a/tests/fake_io_delegate.h
+++ b/tests/fake_io_delegate.h
@@ -68,9 +68,6 @@
   bool PathWasRemoved(const std::string& path);
 
  private:
-  // Remove leading "./" from |path|.
-  std::string CleanPath(const std::string& path) const;
-
   std::map<std::string, std::string> file_contents_;
   // Normally, writing to files leaves the IoDelegate unchanged, so
   // GetCodeWriter is a const method.  However, for tests, we break this