Merge "Add hidl_test_java dependencies in build system."
diff --git a/AST.cpp b/AST.cpp
index f61ad4f..f9a6515 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -21,6 +21,7 @@
 #include "FQName.h"
 #include "HandleType.h"
 #include "Interface.h"
+#include "Location.h"
 #include "PredefinedType.h"
 #include "Scope.h"
 #include "TypeDef.h"
@@ -36,7 +37,7 @@
     : mCoordinator(coordinator),
       mPath(path),
       mScanner(NULL),
-      mRootScope(new Scope("" /* localName */)) {
+      mRootScope(new Scope("" /* localName */, Location::startOf(path))) {
     enterScope(mRootScope);
 }
 
@@ -188,13 +189,13 @@
     return mScopePath.back();
 }
 
-bool AST::addTypeDef(
-        const char *localName, Type *type, std::string *errorMsg) {
+bool AST::addTypeDef(const char *localName, Type *type, const Location &location,
+        std::string *errorMsg) {
     // The reason we wrap the given type in a TypeDef is simply to suppress
     // emitting any type definitions later on, since this is just an alias
     // to a type defined elsewhere.
     return addScopedTypeInternal(
-            new TypeDef(localName, type), errorMsg);
+            new TypeDef(localName, location, type), errorMsg);
 }
 
 bool AST::addScopedType(NamedType *type, std::string *errorMsg) {
diff --git a/AST.h b/AST.h
index 9a3670c..a4b4cda 100644
--- a/AST.h
+++ b/AST.h
@@ -32,6 +32,7 @@
 struct Coordinator;
 struct Formatter;
 struct Interface;
+struct Location;
 struct Method;
 struct NamedType;
 struct TypedVar;
@@ -55,7 +56,8 @@
     Scope *scope();
 
     // Returns true iff successful.
-    bool addTypeDef(const char *localName, Type *type, std::string *errorMsg);
+    bool addTypeDef(const char *localName, Type *type, const Location &location,
+            std::string *errorMsg);
 
     // Returns true iff successful.
     bool addScopedType(NamedType *type, std::string *errorMsg);
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 870402b..a262e17 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -22,8 +22,8 @@
 
 namespace android {
 
-CompoundType::CompoundType(Style style, const char *localName)
-    : Scope(localName),
+CompoundType::CompoundType(Style style, const char *localName, const Location &location)
+    : Scope(localName, location),
       mStyle(style),
       mFields(NULL) {
 }
diff --git a/CompoundType.h b/CompoundType.h
index 3bc3d13..c48f57e 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -32,7 +32,7 @@
         STYLE_UNION,
     };
 
-    CompoundType(Style style, const char *localName);
+    CompoundType(Style style, const char *localName, const Location &location);
 
     bool setFields(std::vector<CompoundField *> *fields, std::string *errorMsg);
 
diff --git a/EnumType.cpp b/EnumType.cpp
index 27c0075..9903b3e 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -27,8 +27,9 @@
 
 EnumType::EnumType(
         const char *localName,
+        const Location &location,
         Type *storageType)
-    : Scope(localName),
+    : Scope(localName, location),
       mValues(),
       mStorageType(
               storageType != NULL
diff --git a/EnumType.h b/EnumType.h
index c464cd2..f9afb31 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -29,6 +29,7 @@
 
 struct EnumType : public Scope {
     EnumType(const char *localName,
+             const Location &location,
              Type *storageType = NULL);
 
     const Type *storageType() const;
diff --git a/Interface.cpp b/Interface.cpp
index f03f3aa..436f836 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -48,8 +48,8 @@
     LAST_HIDL_TRANSACTION   = 0x00ffffff,
 };
 
-Interface::Interface(const char *localName, Interface *super)
-    : Scope(localName),
+Interface::Interface(const char *localName, const Location &location, Interface *super)
+    : Scope(localName, location),
       mSuperType(super),
       mIsJavaCompatibleInProgress(false) {
     mReservedMethods.push_back(createDescriptorChainMethod());
diff --git a/Interface.h b/Interface.h
index 135a69b..1c23186 100644
--- a/Interface.h
+++ b/Interface.h
@@ -27,7 +27,7 @@
 struct InterfaceAndMethod;
 
 struct Interface : public Scope {
-    Interface(const char *localName, Interface *super);
+    Interface(const char *localName, const Location &location, Interface *super);
 
     bool addMethod(Method *method);
 
diff --git a/Location.h b/Location.h
new file mode 100644
index 0000000..84dfc0e
--- /dev/null
+++ b/Location.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef LOCATION_H_
+#define LOCATION_H_
+
+#include <iostream>
+#include <stdint.h>
+#include <string>
+
+// Mimics for yy::location and yy::position
+namespace android {
+
+struct Position {
+    Position(std::string f, size_t l, size_t c)
+            : mFilename(f), mLine(l), mColumn(c) {}
+    inline const std::string &filename() const { return mFilename; }
+    inline size_t line() const { return mLine; }
+    inline size_t column() const { return mColumn; }
+
+private:
+    // File name to which this position refers.
+    const std::string mFilename;
+    // Current line number.
+    const size_t mLine;
+    // Current column number.
+    const size_t mColumn;
+};
+
+inline std::ostream& operator<< (std::ostream& ostr, const Position& pos) {
+    if (!pos.filename().empty()) {
+        ostr << pos.filename() << ":";
+    }
+    return ostr << pos.line() << "." << pos.column();
+}
+
+struct Location {
+    Location (Position begin, Position end)
+            : mBegin(begin), mEnd(end) {}
+    inline const Position &begin() const { return mBegin; }
+    inline const Position &end() const { return mEnd; }
+
+    inline static Location startOf(const std::string &path) {
+        return Location(Position(path, 1, 1), Position(path, 1, 1));
+    }
+
+private:
+    // Beginning of the located region.
+    const Position mBegin;
+    // End of the located region.
+    const Position mEnd;
+};
+
+inline std::ostream& operator<< (std::ostream& ostr, const Location& loc) {
+    Position last = Position(loc.end().filename(),
+            loc.end().line(),
+            std::max<size_t>(1u, loc.end().column() - 1));
+    ostr << loc.begin();
+    if (loc.begin().filename() != last.filename()) {
+        ostr << "-" << last;
+    } else if (loc.begin().line() != last.line()) {
+        ostr << "-" << last.line()  << "." << last.column();
+    } else if (loc.begin().column() != last.column()) {
+        ostr << "-" << last.column();
+    }
+    return ostr;
+}
+
+} // namespace android
+
+#endif
diff --git a/NamedType.cpp b/NamedType.cpp
index 727cca2..939b366 100644
--- a/NamedType.cpp
+++ b/NamedType.cpp
@@ -18,8 +18,8 @@
 
 namespace android {
 
-NamedType::NamedType(const char *localName)
-    : mLocalName(localName) {
+NamedType::NamedType(const char *localName, const Location &loc)
+    : mLocalName(localName), mLocation(loc) {
 }
 
 bool NamedType::isNamedType() const {
@@ -54,5 +54,9 @@
     return mFullName.javaName();
 }
 
+const Location &NamedType::location() const {
+    return mLocation;
+}
+
 }  // namespace android
 
diff --git a/NamedType.h b/NamedType.h
index 53988e2..93940e8 100644
--- a/NamedType.h
+++ b/NamedType.h
@@ -18,16 +18,16 @@
 
 #define NAMED_TYPE_H_
 
-#include "Type.h"
-
 #include "FQName.h"
+#include "Location.h"
+#include "Type.h"
 
 #include <string>
 
 namespace android {
 
 struct NamedType : public Type {
-    NamedType(const char *localName);
+    NamedType(const char *localName, const Location &loc);
 
     bool isNamedType() const override;
 
@@ -46,9 +46,13 @@
     /* short for fqName().fullJavaName() */
     std::string fullJavaName() const;
 
+    // returns null if no location is set for this type.
+    const Location &location() const;
+
 private:
     std::string mLocalName;
     FQName mFullName;
+    Location mLocation;
 
     DISALLOW_COPY_AND_ASSIGN(NamedType);
 };
diff --git a/Scope.cpp b/Scope.cpp
index 8caf9c9..061bc6f 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -24,8 +24,9 @@
 
 namespace android {
 
-Scope::Scope(const char *localName)
-    : NamedType(localName) {
+Scope::Scope(const char *localName,
+        const Location &location)
+    : NamedType(localName, location) {
 }
 Scope::~Scope(){}
 
diff --git a/Scope.h b/Scope.h
index 8d26cac..4fb57ed 100644
--- a/Scope.h
+++ b/Scope.h
@@ -30,7 +30,8 @@
 struct LocalIdentifier;
 
 struct Scope : public NamedType {
-    Scope(const char *localName);
+    Scope(const char *localName,
+          const Location &location);
     virtual ~Scope();
 
     bool addType(NamedType *type, std::string *errorMsg);
diff --git a/TypeDef.cpp b/TypeDef.cpp
index f2e1401..5261829 100644
--- a/TypeDef.cpp
+++ b/TypeDef.cpp
@@ -21,8 +21,8 @@
 
 namespace android {
 
-TypeDef::TypeDef(const char* localName, Type *type)
-    : NamedType(localName),
+TypeDef::TypeDef(const char* localName, const Location &location, Type *type)
+    : NamedType(localName, location),
       mReferencedType(type) {
 }
 
diff --git a/TypeDef.h b/TypeDef.h
index cee93c8..5ccbf01 100644
--- a/TypeDef.h
+++ b/TypeDef.h
@@ -23,7 +23,7 @@
 namespace android {
 
 struct TypeDef : public NamedType {
-    TypeDef(const char* localName, Type *type);
+    TypeDef(const char* localName, const Location &location, Type *type);
 
     const ScalarType *resolveToScalarType() const override;
 
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 266a5f2..8937da4 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -25,6 +25,7 @@
 #include "FQName.h"
 #include "GenericBinder.h"
 #include "Interface.h"
+#include "Location.h"
 #include "Method.h"
 #include "VectorType.h"
 #include "RefType.h"
@@ -40,6 +41,14 @@
 
 #define scanner ast->scanner()
 
+::android::Location convertYYLoc(const yy::parser::location_type &loc) {
+    return ::android::Location(
+            ::android::Position(*(loc.begin.filename), loc.begin.line, loc.begin.column),
+            ::android::Position(*(loc.end.filename), loc.end.line, loc.end.column)
+    );
+}
+
+
 %}
 
 %initial-action {
@@ -396,7 +405,7 @@
               YYERROR;
           }
 
-          Interface *iface = new Interface($2, static_cast<Interface *>($3));
+          Interface *iface = new Interface($2, convertYYLoc(@2), static_cast<Interface *>($3));
 
           // Register interface immediately so it can be referenced inside
           // definition.
@@ -422,7 +431,7 @@
     : TYPEDEF type IDENTIFIER
       {
           std::string errorMsg;
-          if (!ast->addTypeDef($3, $2, &errorMsg)) {
+          if (!ast->addTypeDef($3, $2, convertYYLoc(@3), &errorMsg)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @3 << "\n";
               YYERROR;
           }
@@ -539,7 +548,7 @@
 named_struct_or_union_declaration
     : struct_or_union_keyword IDENTIFIER
       {
-          CompoundType *container = new CompoundType($1, $2);
+          CompoundType *container = new CompoundType($1, $2, convertYYLoc(@2));
           ast->enterScope(container);
       }
       struct_or_union_body
@@ -620,7 +629,7 @@
 named_enum_declaration
     : ENUM IDENTIFIER opt_storage_type
       {
-          ast->enterScope(new EnumType($2, $3));
+          ast->enterScope(new EnumType($2, convertYYLoc(@2), $3));
       }
       enum_declaration_body
       {