aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeel Mehta <mneel@google.com>2019-07-02 15:47:48 -0700
committerNeel Mehta <mneel@google.com>2019-07-19 10:59:40 -0700
commit3b414a8de5643fdf7ff0e1aa6d162830f081c4e4 (patch)
tree0df703db3d8845e6b76d13ebabd271e4be953c37
parent8d5421845fe329fe38fca17f7d1eee736a6e600b (diff)
downloadhidl-3b414a8de5643fdf7ff0e1aa6d162830f081c4e4.tar.gz
Add -Lformat option to format .hal files
Formats .hal files. Bug: 137553653 Test: hidl-gen -Lformat <IFACE> Test: aosp/1051701 Test: hidl-gen -Lformat (google-interfaces) & hidl-gen -Lcheck (google-interfaces) Change-Id: I5aa554d99fd4977acb7939d8c793081680a3f598
-rw-r--r--AST.h2
-rw-r--r--Android.bp1
-rw-r--r--Annotation.cpp2
-rw-r--r--ArrayType.cpp5
-rw-r--r--CompoundType.cpp18
-rw-r--r--CompoundType.h1
-rw-r--r--ConstantExpression.cpp36
-rw-r--r--ConstantExpression.h3
-rw-r--r--DeathRecipientType.cpp2
-rw-r--r--DocComment.cpp12
-rw-r--r--DocComment.h9
-rw-r--r--EnumType.cpp29
-rw-r--r--EnumType.h1
-rw-r--r--FmqType.cpp4
-rw-r--r--FmqType.h2
-rw-r--r--FormattingConstants.h23
-rw-r--r--HandleType.cpp2
-rw-r--r--Interface.cpp25
-rw-r--r--Interface.h2
-rw-r--r--MemoryType.cpp2
-rw-r--r--Method.cpp50
-rw-r--r--Method.h2
-rw-r--r--NamedType.cpp3
-rw-r--r--PointerType.cpp2
-rw-r--r--Reference.h26
-rw-r--r--ScalarType.cpp7
-rw-r--r--Scope.cpp16
-rw-r--r--Scope.h7
-rw-r--r--StringType.cpp2
-rw-r--r--Type.cpp16
-rw-r--r--Type.h15
-rw-r--r--TypeDef.cpp4
-rw-r--r--TypeDef.h3
-rw-r--r--VectorType.cpp2
-rw-r--r--generateFormattedHidl.cpp44
-rw-r--r--hidl-gen_l.ll4
-rw-r--r--hidl-gen_y.yy26
-rw-r--r--host_utils/Formatter.cpp146
-rw-r--r--host_utils/include/hidl-util/Formatter.h44
-rw-r--r--main.cpp15
-rw-r--r--utils/FQName.cpp25
-rw-r--r--utils/include/hidl-util/FQName.h7
42 files changed, 577 insertions, 70 deletions
diff --git a/AST.h b/AST.h
index 47f08469..e9c1367d 100644
--- a/AST.h
+++ b/AST.h
@@ -161,6 +161,8 @@ struct AST {
void generateDependencies(Formatter& out) const;
void generateInheritanceHierarchy(Formatter& out) const;
+ void generateFormattedHidl(Formatter& out) const;
+
const std::vector<ImportStatement>& getImportStatements() const;
void getImportedPackages(std::set<FQName> *importSet) const;
diff --git a/Android.bp b/Android.bp
index 830be46d..b712dbe7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -110,6 +110,7 @@ cc_library_host_shared {
"generateCppAdapter.cpp",
"generateCppImpl.cpp",
"generateDependencies.cpp",
+ "generateFormattedHidl.cpp",
"generateInheritanceHierarchy.cpp",
"generateJava.cpp",
"generateJavaImpl.cpp",
diff --git a/Annotation.cpp b/Annotation.cpp
index 438cff65..4c9637fd 100644
--- a/Annotation.cpp
+++ b/Annotation.cpp
@@ -158,7 +158,7 @@ void Annotation::dump(Formatter &out) const {
const AnnotationParam* param = mParams->at(i);
- out << param->getName() << "=";
+ out << param->getName() << " = ";
const std::vector<std::string>& values = param->getValues();
if (values.size() > 1) {
diff --git a/ArrayType.cpp b/ArrayType.cpp
index 33424d84..5e491cf0 100644
--- a/ArrayType.cpp
+++ b/ArrayType.cpp
@@ -25,12 +25,15 @@
namespace android {
ArrayType::ArrayType(const Reference<Type>& elementType, ConstantExpression* size, Scope* parent)
- : Type(parent), mElementType(elementType), mSizes{size} {
+ : Type(parent, elementType.localName()), mElementType(elementType) {
CHECK(!elementType.isEmptyReference());
+
+ appendDimension(size);
}
void ArrayType::appendDimension(ConstantExpression *size) {
mSizes.push_back(size);
+ mDefinedName = mDefinedName + "[" + size->expression() + "]";
}
size_t ArrayType::countDimensions() const {
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 68bcedf0..a431912b 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -632,6 +632,24 @@ void CompoundType::emitSafeUnionTypeDeclarations(Formatter& out) const {
}
}
+void CompoundType::emitHidlDefinition(Formatter& out) const {
+ if (getDocComment() != nullptr) getDocComment()->emit(out);
+ out << typeName() << " ";
+
+ out.block([&] {
+ for (const Type* t : getSortedDefinedTypes()) {
+ t->emitHidlDefinition(out);
+ }
+
+ for (const NamedReference<Type>* ref : *mFields) {
+ if (ref->getDocComment() != nullptr) ref->getDocComment()->emit(out);
+ out << ref->localName() << " " << ref->name() << ";\n";
+ }
+ });
+
+ out << ";\n";
+}
+
void CompoundType::emitTypeDeclarations(Formatter& out) const {
if (mStyle == STYLE_SAFE_UNION) {
emitSafeUnionTypeDeclarations(out);
diff --git a/CompoundType.h b/CompoundType.h
index 3dec6afd..2c5a055c 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -100,6 +100,7 @@ struct CompoundType : public Scope {
const std::string &offset,
bool isReader) const override;
+ void emitHidlDefinition(Formatter& out) const override;
void emitTypeDeclarations(Formatter& out) const override;
void emitTypeForwardDeclaration(Formatter& out) const override;
void emitPackageTypeDeclarations(Formatter& out) const override;
diff --git a/ConstantExpression.cpp b/ConstantExpression.cpp
index 002bf566..6badf579 100644
--- a/ConstantExpression.cpp
+++ b/ConstantExpression.cpp
@@ -164,17 +164,19 @@ std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind
return std::make_unique<LiteralConstantExpression>(kind, value);
}
+ConstantExpression::ConstantExpression(const std::string& expr) : mExpr(expr) {}
+
bool ConstantExpression::isEvaluated() const {
return mIsEvaluated;
}
-LiteralConstantExpression::LiteralConstantExpression(
- ScalarType::Kind kind, uint64_t value, const std::string& expr) {
-
+LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value,
+ const std::string& expr)
+ : ConstantExpression(expr) {
CHECK(!expr.empty());
CHECK(isSupported(kind));
+
mTrivialDescription = std::to_string(value) == expr;
- mExpr = expr;
mValueKind = kind;
mValue = value;
mIsEvaluated = true;
@@ -254,7 +256,6 @@ void UnaryConstantExpression::evaluate() {
CHECK(mUnary->isEvaluated());
mIsEvaluated = true;
- mExpr = std::string("(") + mOp + mUnary->mExpr + ")";
mValueKind = mUnary->mValueKind;
#define CASE_UNARY(__type__) \
@@ -270,8 +271,6 @@ void BinaryConstantExpression::evaluate() {
CHECK(mRval->isEvaluated());
mIsEvaluated = true;
- mExpr = std::string("(") + mLval->mExpr + " " + mOp + " " + mRval->mExpr + ")";
-
bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
// CASE 1: + - * / % | ^ & < > <= >= == !=
@@ -330,8 +329,6 @@ void TernaryConstantExpression::evaluate() {
CHECK(mFalseVal->isEvaluated());
mIsEvaluated = true;
- mExpr = std::string("(") + mCond->mExpr + "?" + mTrueVal->mExpr + ":" + mFalseVal->mExpr + ")";
-
// note: for ?:, unlike arithmetic ops, integral promotion is not processed.
mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
@@ -466,7 +463,6 @@ std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
}
const std::string& ConstantExpression::expression() const {
- CHECK(isEvaluated());
return mExpr;
}
@@ -683,7 +679,7 @@ std::vector<const ConstantExpression*> LiteralConstantExpression::getConstantExp
}
UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
- : mUnary(value), mOp(op) {}
+ : ConstantExpression(std::string("(") + op + value->mExpr + ")"), mUnary(value), mOp(op) {}
std::vector<const ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
return {mUnary};
@@ -691,7 +687,10 @@ std::vector<const ConstantExpression*> UnaryConstantExpression::getConstantExpre
BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
ConstantExpression* rval)
- : mLval(lval), mRval(rval), mOp(op) {}
+ : ConstantExpression(std::string("(") + lval->mExpr + " " + op + " " + rval->mExpr + ")"),
+ mLval(lval),
+ mRval(rval),
+ mOp(op) {}
std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
return {mLval, mRval};
@@ -700,7 +699,11 @@ std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpr
TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
ConstantExpression* trueVal,
ConstantExpression* falseVal)
- : mCond(cond), mTrueVal(trueVal), mFalseVal(falseVal) {}
+ : ConstantExpression(std::string("(") + cond->mExpr + "?" + trueVal->mExpr + ":" +
+ falseVal->mExpr + ")"),
+ mCond(cond),
+ mTrueVal(trueVal),
+ mFalseVal(falseVal) {}
std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
return {mCond, mTrueVal, mFalseVal};
@@ -708,8 +711,7 @@ std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExp
ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
const std::string& expr)
- : mReference(value) {
- mExpr = expr;
+ : ConstantExpression(expr), mReference(value) {
mTrivialDescription = mExpr.empty();
}
@@ -729,9 +731,7 @@ std::vector<const Reference<LocalIdentifier>*> ReferenceConstantExpression::getR
AttributeConstantExpression::AttributeConstantExpression(const Reference<Type>& value,
const std::string& fqname,
const std::string& tag)
- : mReference(value), mTag(tag) {
- mExpr = fqname + "#" + tag;
-}
+ : ConstantExpression(fqname + "#" + tag), mReference(value), mTag(tag) {}
std::vector<const ConstantExpression*> AttributeConstantExpression::getConstantExpressions() const {
// Returns reference instead
diff --git a/ConstantExpression.h b/ConstantExpression.h
index b7707166..9f20fd5d 100644
--- a/ConstantExpression.h
+++ b/ConstantExpression.h
@@ -46,6 +46,7 @@ struct ConstantExpression {
static std::unique_ptr<ConstantExpression> One(ScalarType::Kind kind);
static std::unique_ptr<ConstantExpression> ValueOf(ScalarType::Kind kind, uint64_t value);
+ ConstantExpression(const std::string& expr);
virtual ~ConstantExpression() {}
virtual bool isReferenceConstantExpression() const;
@@ -136,7 +137,7 @@ struct ConstantExpression {
/* If the result value has been evaluated. */
bool mIsEvaluated = false;
/* The formatted expression. */
- std::string mExpr;
+ const std::string mExpr;
/* The kind of the result value. */
ScalarType::Kind mValueKind;
/* The stored result value. */
diff --git a/DeathRecipientType.cpp b/DeathRecipientType.cpp
index abc69fcc..1aa22ed0 100644
--- a/DeathRecipientType.cpp
+++ b/DeathRecipientType.cpp
@@ -21,7 +21,7 @@
namespace android {
-DeathRecipientType::DeathRecipientType(Scope* parent) : Type(parent) {}
+DeathRecipientType::DeathRecipientType(Scope* parent) : Type(parent, "death_recipient") {}
std::string DeathRecipientType::typeName() const {
return "death recipient";
diff --git a/DocComment.cpp b/DocComment.cpp
index 707679a5..2a1c9816 100644
--- a/DocComment.cpp
+++ b/DocComment.cpp
@@ -63,8 +63,16 @@ void DocComment::merge(const DocComment* comment) {
mLocation.setLocation(mLocation.begin(), comment->mLocation.end());
}
-void DocComment::emit(Formatter& out) const {
- out << "/**\n";
+void DocComment::emit(Formatter& out, CommentType type) const {
+ switch (type) {
+ case CommentType::DOC_MULTILINE:
+ out << "/**\n";
+ break;
+ case CommentType::MULTILINE:
+ out << "/*\n";
+ break;
+ }
+
out.setLinePrefix(" *");
for (const std::string& line : mLines) {
diff --git a/DocComment.h b/DocComment.h
index 58c8e17a..315ef607 100644
--- a/DocComment.h
+++ b/DocComment.h
@@ -27,12 +27,19 @@
namespace android {
+enum class CommentType {
+ // multiline comment that begins with /**
+ DOC_MULTILINE,
+ // begins with /* (used for headers)
+ MULTILINE
+};
+
struct DocComment {
DocComment(const std::string& comment, const Location& location);
void merge(const DocComment* comment);
- void emit(Formatter& out) const;
+ void emit(Formatter& out, CommentType type = CommentType::DOC_MULTILINE) const;
const std::vector<std::string>& lines() const { return mLines; }
diff --git a/EnumType.cpp b/EnumType.cpp
index 6a3a002c..d0e88a35 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -251,6 +251,31 @@ void EnumType::emitJavaFieldReaderWriter(
out, depth, parcelName, blobName, fieldName, offset, isReader);
}
+void EnumType::emitHidlDefinition(Formatter& out) const {
+ if (getDocComment() != nullptr) getDocComment()->emit(out);
+
+ if (annotations().size() != 0) {
+ out.join(annotations().begin(), annotations().end(), " ",
+ [&](auto annotation) { annotation->dump(out); });
+ out << "\n";
+ }
+
+ out << typeName() << " : " << mStorageType.localName() << " {\n";
+
+ out.indent([&] {
+ for (const EnumValue* val : mValues) {
+ if (val->getDocComment() != nullptr) val->getDocComment()->emit(out);
+ out << val->name();
+ if (!val->isAutoFill()) {
+ out << " = " << val->constExpr()->expression();
+ }
+ out << ",\n";
+ }
+ });
+
+ out << "};\n";
+}
+
void EnumType::emitTypeDeclarations(Formatter& out) const {
const ScalarType *scalarType = mStorageType->resolveToScalarType();
CHECK(scalarType != nullptr);
@@ -783,7 +808,7 @@ void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const S
} else {
std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly";
auto* prevReference = new ReferenceConstantExpression(
- Reference<LocalIdentifier>(prevValue, mLocation), description);
+ Reference<LocalIdentifier>(prevValue->mName, prevValue, mLocation), description);
mValue = prevReference->addOne(type->getKind()).release();
}
}
@@ -802,7 +827,7 @@ const Location& EnumValue::location() const {
////////////////////////////////////////////////////////////////////////////////
-BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent) {}
+BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent, "bitfield") {}
bool BitFieldType::isBitField() const {
return true;
diff --git a/EnumType.h b/EnumType.h
index b429e395..ab796d12 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -96,6 +96,7 @@ struct EnumType : public Scope {
const std::string &offset,
bool isReader) const override;
+ void emitHidlDefinition(Formatter& out) const override;
void emitTypeDeclarations(Formatter& out) const override;
void emitTypeForwardDeclaration(Formatter& out) const override;
void emitGlobalTypeDeclarations(Formatter& out) const override;
diff --git a/FmqType.cpp b/FmqType.cpp
index f5eaaa68..ed323f2e 100644
--- a/FmqType.cpp
+++ b/FmqType.cpp
@@ -23,8 +23,8 @@
namespace android {
-FmqType::FmqType(const char* nsp, const char* name, Scope* parent)
- : TemplatedType(parent), mNamespace(nsp), mName(name) {}
+FmqType::FmqType(const char* nsp, const char* name, Scope* parent, const char* definedName)
+ : TemplatedType(parent, definedName), mNamespace(nsp), mName(name) {}
std::string FmqType::templatedTypeName() const {
return mName;
diff --git a/FmqType.h b/FmqType.h
index 747b10a6..f6b1f186 100644
--- a/FmqType.h
+++ b/FmqType.h
@@ -23,7 +23,7 @@
namespace android {
struct FmqType : public TemplatedType {
- FmqType(const char* nsp, const char* name, Scope* parent);
+ FmqType(const char* nsp, const char* name, Scope* parent, const char* definedName);
std::string fullName() const;
diff --git a/FormattingConstants.h b/FormattingConstants.h
new file mode 100644
index 00000000..1ab5a179
--- /dev/null
+++ b/FormattingConstants.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <cstddef>
+
+namespace android {
+constexpr size_t MAX_LINE_LENGTH = 100;
+}; \ No newline at end of file
diff --git a/HandleType.cpp b/HandleType.cpp
index 56660a6e..1c612e59 100644
--- a/HandleType.cpp
+++ b/HandleType.cpp
@@ -23,7 +23,7 @@
namespace android {
-HandleType::HandleType(Scope* parent) : Type(parent) {}
+HandleType::HandleType(Scope* parent) : Type(parent, "handle") {}
bool HandleType::isHandle() const {
return true;
diff --git a/Interface.cpp b/Interface.cpp
index b6d2f38d..ff33972d 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -822,6 +822,31 @@ void Interface::emitReaderWriter(
}
}
+void Interface::emitHidlDefinition(Formatter& out) const {
+ if (getDocComment() != nullptr) getDocComment()->emit(out);
+ out << typeName() << " ";
+
+ const Interface* super = superType();
+ if (super != nullptr && !super->isIBase()) {
+ out << "extends " << super->fqName().getRelativeFQName(fqName()) << " ";
+ }
+
+ out << "{\n";
+
+ out.indent([&] {
+ const std::vector<const NamedType*>& definedTypes = getSortedDefinedTypes();
+ out.join(definedTypes.begin(), definedTypes.end(), "\n",
+ [&](auto t) { t->emitHidlDefinition(out); });
+
+ if (definedTypes.size() > 0 && userDefinedMethods().size() > 0) out << "\n";
+
+ out.join(userDefinedMethods().begin(), userDefinedMethods().end(), "\n",
+ [&](auto method) { method->emitHidlDefinition(out); });
+ });
+
+ out << "};\n";
+}
+
void Interface::emitPackageTypeDeclarations(Formatter& out) const {
Scope::emitPackageTypeDeclarations(out);
diff --git a/Interface.h b/Interface.h
index 56570f5c..e0fcb8b2 100644
--- a/Interface.h
+++ b/Interface.h
@@ -111,6 +111,8 @@ struct Interface : public Scope {
bool isReader,
ErrorMode mode) const override;
+ void emitHidlDefinition(Formatter& out) const override;
+
void emitPackageTypeDeclarations(Formatter& out) const override;
void emitPackageTypeHeaderDefinitions(Formatter& out) const override;
void emitTypeDefinitions(Formatter& out, const std::string& prefix) const override;
diff --git a/MemoryType.cpp b/MemoryType.cpp
index 444ba92c..380214fa 100644
--- a/MemoryType.cpp
+++ b/MemoryType.cpp
@@ -23,7 +23,7 @@
namespace android {
-MemoryType::MemoryType(Scope* parent) : Type(parent) {}
+MemoryType::MemoryType(Scope* parent) : Type(parent, "memory") {}
std::string MemoryType::getCppType(StorageMode mode,
bool specifyNamespaces) const {
diff --git a/Method.cpp b/Method.cpp
index 7954462d..42b4d5cf 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -18,12 +18,15 @@
#include "Annotation.h"
#include "ConstantExpression.h"
+#include "FormattingConstants.h"
#include "ScalarType.h"
#include "Type.h"
#include <android-base/logging.h>
+#include <hidl-util/FQName.h>
#include <hidl-util/Formatter.h>
#include <algorithm>
+#include <vector>
namespace android {
@@ -263,6 +266,53 @@ void Method::emitJavaSignature(Formatter& out) const {
out << ")";
}
+static void fillHidlArgResultTokens(const std::vector<NamedReference<Type>*>& args,
+ WrappedOutput* wrappedOutput) {
+ for (auto iter = args.begin(); iter != args.end(); ++iter) {
+ auto arg = *iter;
+ std::string out = arg->localName() + " " + arg->name();
+ if (iter != args.begin()) {
+ *wrappedOutput << ",";
+ wrappedOutput->group([&] {
+ wrappedOutput->printUnlessWrapped(" ");
+ *wrappedOutput << out;
+ });
+ } else {
+ wrappedOutput->group([&] { *wrappedOutput << out; });
+ }
+ }
+}
+
+void Method::emitHidlDefinition(Formatter& out) const {
+ if (getDocComment() != nullptr) getDocComment()->emit(out);
+
+ out.join(mAnnotations->begin(), mAnnotations->end(), "\n",
+ [&](auto annotation) { annotation->dump(out); });
+ if (!mAnnotations->empty()) out << "\n";
+
+ WrappedOutput wrappedOutput(MAX_LINE_LENGTH);
+
+ if (isOneway()) wrappedOutput << "oneway ";
+ wrappedOutput << name() << "(";
+
+ wrappedOutput.group([&] { fillHidlArgResultTokens(args(), &wrappedOutput); });
+
+ wrappedOutput << ")";
+
+ if (!results().empty()) {
+ wrappedOutput.group([&] {
+ wrappedOutput.printUnlessWrapped(" ");
+ wrappedOutput << "generates (";
+ fillHidlArgResultTokens(results(), &wrappedOutput);
+ wrappedOutput << ")";
+ });
+ }
+
+ wrappedOutput << ";\n";
+
+ out << wrappedOutput;
+}
+
bool Method::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
if (!std::all_of(mArgs->begin(), mArgs->end(),
[&](const auto* arg) { return (*arg)->isJavaCompatible(visited); })) {
diff --git a/Method.h b/Method.h
index 4b43a4bc..5c5ac476 100644
--- a/Method.h
+++ b/Method.h
@@ -103,6 +103,8 @@ struct Method : DocCommentable {
void emitJavaResultSignature(Formatter &out) const;
void emitJavaSignature(Formatter& out) const;
+ void emitHidlDefinition(Formatter& out) const;
+
const NamedReference<Type>* canElideCallback() const;
bool deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const;
diff --git a/NamedType.cpp b/NamedType.cpp
index 645c63d8..dba92487 100644
--- a/NamedType.cpp
+++ b/NamedType.cpp
@@ -20,7 +20,7 @@ namespace android {
NamedType::NamedType(const char* localName, const FQName& fullName, const Location& loc,
Scope* parent)
- : Type(parent), mLocalName(localName), mFullName(fullName), mLocation(loc) {}
+ : Type(parent, localName), mLocalName(localName), mFullName(fullName), mLocation(loc) {}
bool NamedType::isNamedType() const {
return true;
@@ -54,4 +54,3 @@ void NamedType::emitDump(
}
} // namespace android
-
diff --git a/PointerType.cpp b/PointerType.cpp
index 2b8e5a48..f6eaf541 100644
--- a/PointerType.cpp
+++ b/PointerType.cpp
@@ -21,7 +21,7 @@
namespace android {
-PointerType::PointerType(Scope* parent) : Type(parent) {}
+PointerType::PointerType(Scope* parent) : Type(parent, "pointer") {}
bool PointerType::isPointer() const {
return true;
diff --git a/Reference.h b/Reference.h
index ba39ac42..b8175148 100644
--- a/Reference.h
+++ b/Reference.h
@@ -21,6 +21,8 @@
#include <android-base/logging.h>
#include <hidl-util/FQName.h>
+#include <string>
+
#include "DocComment.h"
#include "Location.h"
@@ -34,20 +36,27 @@ struct Reference {
Reference() = default;
virtual ~Reference() {}
- Reference(const FQName& fqName, const Location& location)
- : mResolved(nullptr), mFqName(fqName), mLocation(location) {}
+ Reference(const std::string& localName, const FQName& fqName, const Location& location)
+ : mResolved(nullptr), mFqName(fqName), mLocation(location), mLocalName(localName) {}
- Reference(T* type, const Location& location) : mResolved(type), mLocation(location) {
+ Reference(const std::string& localName, T* type, const Location& location)
+ : mResolved(type), mLocation(location), mLocalName(localName) {
CHECK(type != nullptr);
}
template <class OtherT>
Reference(const Reference<OtherT>& ref)
- : mResolved(ref.mResolved), mFqName(ref.mFqName), mLocation(ref.mLocation) {}
+ : mResolved(ref.mResolved),
+ mFqName(ref.mFqName),
+ mLocation(ref.mLocation),
+ mLocalName(ref.mLocalName) {}
template <class OtherT>
Reference(const Reference<OtherT>& ref, const Location& location)
- : mResolved(ref.mResolved), mFqName(ref.mFqName), mLocation(location) {}
+ : mResolved(ref.mResolved),
+ mFqName(ref.mFqName),
+ mLocation(location),
+ mLocalName(ref.mLocalName) {}
/* Returns true iff referred type is resolved
Referred type's field might be not resolved */
@@ -100,7 +109,9 @@ struct Reference {
return mLocation;
}
- private:
+ const std::string& localName() const { return mLocalName; }
+
+ private:
/* Referred type */
T* mResolved = nullptr;
/* Reference name for lookup */
@@ -109,6 +120,9 @@ struct Reference {
and handling forward reference restrictions */
Location mLocation;
+ /* Name used in the .hal file */
+ std::string mLocalName;
+
bool hasLookupFqName() const {
// Valid only while not resolved to prevent confusion when
// ref.hasLookupFqName() is false while ref,get()->fqName is valid.
diff --git a/ScalarType.cpp b/ScalarType.cpp
index e6f3fe49..142aac27 100644
--- a/ScalarType.cpp
+++ b/ScalarType.cpp
@@ -20,7 +20,12 @@
namespace android {
-ScalarType::ScalarType(Kind kind, Scope* parent) : Type(parent), mKind(kind) {}
+static const char* const hidlIdentifiers[] = {"bool", "int8_t", "uint8_t", "int16_t",
+ "uint16_t", "int32_t", "uint32_t", "int64_t",
+ "uint64_t", "float", "double"};
+
+ScalarType::ScalarType(Kind kind, Scope* parent)
+ : Type(parent, hidlIdentifiers[kind]), mKind(kind) {}
const ScalarType *ScalarType::resolveToScalarType() const {
return this;
diff --git a/Scope.cpp b/Scope.cpp
index d4953aa5..cfe004d1 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -122,6 +122,16 @@ std::vector<const Type*> Scope::getDefinedTypes() const {
return ret;
}
+std::vector<const NamedType*> Scope::getSortedDefinedTypes() const {
+ std::vector<const NamedType*> ret;
+ ret.insert(ret.end(), mTypes.begin(), mTypes.end());
+
+ std::sort(ret.begin(), ret.end(), [](const NamedType* lhs, const NamedType* rhs) -> bool {
+ return lhs->location() < rhs->location();
+ });
+ return ret;
+}
+
std::vector<const ConstantExpression*> Scope::getConstantExpressions() const {
std::vector<const ConstantExpression*> ret;
for (const auto* annotation : mAnnotations) {
@@ -146,6 +156,12 @@ void Scope::topologicalReorder(const std::unordered_map<const Type*, size_t>& re
}
}
+void Scope::emitHidlDefinition(Formatter& out) const {
+ const std::vector<const NamedType*>& definedTypes = getSortedDefinedTypes();
+ out.join(definedTypes.begin(), definedTypes.end(), "\n",
+ [&](auto t) { t->emitHidlDefinition(out); });
+}
+
void Scope::emitTypeDeclarations(Formatter& out) const {
if (mTypes.empty()) return;
diff --git a/Scope.h b/Scope.h
index bf7d1cd7..a62bad82 100644
--- a/Scope.h
+++ b/Scope.h
@@ -69,6 +69,8 @@ struct Scope : public NamedType {
void emitPackageTypeHeaderDefinitions(Formatter& out) const override;
void emitPackageHwDeclarations(Formatter& out) const override;
+ void emitHidlDefinition(Formatter& out) const override;
+
void emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const override;
void emitTypeDefinitions(Formatter& out, const std::string& prefix) const override;
@@ -82,7 +84,10 @@ struct Scope : public NamedType {
void appendToExportedTypesVector(
std::vector<const Type *> *exportedTypes) const override;
- private:
+ protected:
+ std::vector<const NamedType*> getSortedDefinedTypes() const;
+
+ private:
std::vector<NamedType *> mTypes;
std::map<std::string, size_t> mTypeIndexByName;
std::vector<Annotation*> mAnnotations;
diff --git a/StringType.cpp b/StringType.cpp
index b4f72bee..edb183f7 100644
--- a/StringType.cpp
+++ b/StringType.cpp
@@ -22,7 +22,7 @@
namespace android {
-StringType::StringType(Scope* parent) : Type(parent) {}
+StringType::StringType(Scope* parent) : Type(parent, "string") {}
bool StringType::isString() const {
return true;
diff --git a/Type.cpp b/Type.cpp
index d5766155..80bce2a9 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -25,10 +25,12 @@
#include <hidl-util/Formatter.h>
#include <algorithm>
#include <iostream>
+#include <string>
namespace android {
-Type::Type(Scope* parent) : mParent(parent) {}
+Type::Type(Scope* parent, const std::string& definedName)
+ : mDefinedName(definedName), mParent(parent) {}
Type::~Type() {}
@@ -369,6 +371,10 @@ const Scope* Type::parent() const {
return mParent;
}
+const std::string& Type::definedName() const {
+ return mDefinedName;
+}
+
std::string Type::getCppType(StorageMode, bool) const {
CHECK(!"Should not be here") << typeName();
return std::string();
@@ -597,6 +603,10 @@ void Type::emitReaderWriterEmbeddedForTypeName(
handleError(out, mode);
}
+void Type::emitHidlDefinition(Formatter&) const {
+ CHECK(!"Should not be here.") << typeName();
+}
+
void Type::emitTypeDeclarations(Formatter&) const {}
void Type::emitTypeForwardDeclaration(Formatter&) const {}
@@ -725,7 +735,8 @@ bool Type::isNeverStrongReference() const {
////////////////////////////////////////
-TemplatedType::TemplatedType(Scope* parent) : Type(parent) {}
+TemplatedType::TemplatedType(Scope* parent, const std::string& definedName)
+ : Type(parent, definedName) {}
std::string TemplatedType::typeName() const {
return templatedTypeName() + " of " + mElementType->typeName();
@@ -737,6 +748,7 @@ void TemplatedType::setElementType(const Reference<Type>& elementType) {
CHECK(!elementType.isEmptyReference());
mElementType = elementType;
+ mDefinedName = mDefinedName + "<" + mElementType.localName() + ">";
}
const Type* TemplatedType::getElementType() const {
diff --git a/Type.h b/Type.h
index 61310682..0ed120b3 100644
--- a/Type.h
+++ b/Type.h
@@ -38,7 +38,7 @@ struct ScalarType;
struct Scope;
struct Type : DocCommentable {
- Type(Scope* parent);
+ Type(Scope* parent, const std::string& definedName);
virtual ~Type();
virtual bool isArray() const;
@@ -147,6 +147,8 @@ struct Type : DocCommentable {
Scope* parent();
const Scope* parent() const;
+ const std::string& definedName() const;
+
enum StorageMode {
StorageMode_Stack,
StorageMode_Argument,
@@ -251,6 +253,8 @@ struct Type : DocCommentable {
const std::string &offset,
bool isReader) const;
+ virtual void emitHidlDefinition(Formatter& out) const;
+
virtual void emitTypeDeclarations(Formatter& out) const;
virtual void emitGlobalTypeDeclarations(Formatter& out) const;
@@ -344,7 +348,10 @@ struct Type : DocCommentable {
const std::string &methodName,
const std::string &name) const;
- private:
+ // This is the name given to the type in the hidl file
+ std::string mDefinedName;
+
+ private:
ParseStage mParseStage = ParseStage::PARSE;
Scope* const mParent;
@@ -370,8 +377,8 @@ struct TemplatedType : public Type {
void emitVtsAttributeType(Formatter& out) const override;
protected:
- TemplatedType(Scope* parent);
- Reference<Type> mElementType;
+ TemplatedType(Scope* parent, const std::string& definedName);
+ Reference<Type> mElementType;
private:
DISALLOW_COPY_AND_ASSIGN(TemplatedType);
diff --git a/TypeDef.cpp b/TypeDef.cpp
index 80522a28..2e36c285 100644
--- a/TypeDef.cpp
+++ b/TypeDef.cpp
@@ -80,5 +80,9 @@ void TypeDef::emitTypeDeclarations(Formatter& out) const {
<< ";\n\n";
}
+void TypeDef::emitHidlDefinition(Formatter& out) const {
+ out << "typedef " << mReferencedType.localName() << " " << localName() << ";\n";
+}
+
} // namespace android
diff --git a/TypeDef.h b/TypeDef.h
index 5ebba3eb..d6207655 100644
--- a/TypeDef.h
+++ b/TypeDef.h
@@ -44,8 +44,9 @@ struct TypeDef : public NamedType {
std::vector<const Reference<Type>*> getReferences() const override;
void emitTypeDeclarations(Formatter& out) const override;
+ void emitHidlDefinition(Formatter& out) const override;
- private:
+ private:
Reference<Type> mReferencedType;
DISALLOW_COPY_AND_ASSIGN(TypeDef);
diff --git a/VectorType.cpp b/VectorType.cpp
index b5e8e225..3bd2d383 100644
--- a/VectorType.cpp
+++ b/VectorType.cpp
@@ -25,7 +25,7 @@
namespace android {
-VectorType::VectorType(Scope* parent) : TemplatedType(parent) {}
+VectorType::VectorType(Scope* parent) : TemplatedType(parent, "vec") {}
std::string VectorType::templatedTypeName() const {
return "vector";
diff --git a/generateFormattedHidl.cpp b/generateFormattedHidl.cpp
new file mode 100644
index 00000000..742652e2
--- /dev/null
+++ b/generateFormattedHidl.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <hidl-util/FQName.h>
+#include <hidl-util/Formatter.h>
+
+#include "AST.h"
+
+namespace android {
+
+void AST::generateFormattedHidl(Formatter& out) const {
+ if (mHeader != nullptr) {
+ mHeader->emit(out, CommentType::MULTILINE);
+ out << "\n";
+ }
+
+ out << "package " << mPackage.string() << ";\n\n";
+
+ out.join(mImportStatements.begin(), mImportStatements.end(), "\n", [&](const auto& import) {
+ if (import.fqName.name().empty()) {
+ out << "import " << import.fqName.string() << ";";
+ } else {
+ out << "import " << import.fqName.getRelativeFQName(mPackage) << ";";
+ }
+ });
+ if (!mImportStatements.empty()) out << "\n\n";
+
+ mRootScope.emitHidlDefinition(out);
+}
+
+} // namespace android
diff --git a/hidl-gen_l.ll b/hidl-gen_l.ll
index 81fe1511..7d768329 100644
--- a/hidl-gen_l.ll
+++ b/hidl-gen_l.ll
@@ -129,8 +129,8 @@ using token = yy::parser::token;
"pointer" { yylval->type = new PointerType(*scope); return token::TYPE; }
"string" { yylval->type = new StringType(*scope); return token::TYPE; }
-"fmq_sync" { yylval->type = new FmqType("::android::hardware", "MQDescriptorSync", *scope); return token::TEMPLATED; }
-"fmq_unsync" { yylval->type = new FmqType("::android::hardware", "MQDescriptorUnsync", *scope); return token::TEMPLATED; }
+"fmq_sync" { yylval->type = new FmqType("::android::hardware", "MQDescriptorSync", *scope, "fmq_sync"); return token::TEMPLATED; }
+"fmq_unsync" { yylval->type = new FmqType("::android::hardware", "MQDescriptorUnsync", *scope, "fmq_unsync"); return token::TEMPLATED; }
"(" { return('('); }
")" { return(')'); }
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 58f78d05..7d4650d3 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -529,11 +529,11 @@ fqname
fqtype
: fqname
{
- $$ = new Reference<Type>(*$1, convertYYLoc(@1, ast));
+ $$ = new Reference<Type>($1->string(), *$1, convertYYLoc(@1, ast));
}
| TYPE
{
- $$ = new Reference<Type>($1, convertYYLoc(@1, ast));
+ $$ = new Reference<Type>($1->definedName(), $1, convertYYLoc(@1, ast));
}
;
@@ -713,7 +713,7 @@ interface_declaration
}
if (superType == nullptr) {
- superType = new Reference<Type>(gIBaseFqName, convertYYLoc(@$, ast));
+ superType = new Reference<Type>(gIBaseFqName.string(), gIBaseFqName, convertYYLoc(@$, ast));
}
}
@@ -788,12 +788,12 @@ const_expr
}
$$ = new ReferenceConstantExpression(
- Reference<LocalIdentifier>(*$1, convertYYLoc(@1, ast)), $1->string());
+ Reference<LocalIdentifier>($1->string(), *$1, convertYYLoc(@1, ast)), $1->string());
}
| fqname '#' IDENTIFIER
{
$$ = new AttributeConstantExpression(
- Reference<Type>(*$1, convertYYLoc(@1, ast)), $1->string(), $3);
+ Reference<Type>($1->string(), *$1, convertYYLoc(@1, ast)), $1->string(), $3);
}
| const_expr '?' const_expr ':' const_expr
{
@@ -1045,8 +1045,8 @@ named_enum_declaration
std::cerr << "ERROR: Must explicitly specify enum storage type for "
<< $2 << " at " << @2 << "\n";
ast->addSyntaxError();
- storageType = new Reference<Type>(
- new ScalarType(ScalarType::KIND_INT64, *scope), convertYYLoc(@2, ast));
+ ScalarType* scalar = new ScalarType(ScalarType::KIND_INT64, *scope);
+ storageType = new Reference<Type>(scalar->definedName(), scalar, convertYYLoc(@2, ast));
}
EnumType* enumType = new EnumType(
@@ -1123,13 +1123,13 @@ array_type_base
| TEMPLATED '<' type '>'
{
$1->setElementType(*$3);
- $$ = new Reference<Type>($1, convertYYLoc(@1, ast));
+ $$ = new Reference<Type>($1->definedName(), $1, convertYYLoc(@1, ast));
}
| TEMPLATED '<' TEMPLATED '<' type RSHIFT
{
$3->setElementType(*$5);
- $1->setElementType(Reference<Type>($3, convertYYLoc(@3, ast)));
- $$ = new Reference<Type>($1, convertYYLoc(@1, ast));
+ $1->setElementType(Reference<Type>($3->definedName(), $3, convertYYLoc(@3, ast)));
+ $$ = new Reference<Type>($1->definedName(), $1, convertYYLoc(@1, ast));
}
;
@@ -1149,12 +1149,12 @@ type
: array_type_base ignore_doc_comments { $$ = $1; }
| array_type ignore_doc_comments
{
- $$ = new Reference<Type>($1, convertYYLoc(@1, ast));
+ $$ = new Reference<Type>($1->definedName(), $1, convertYYLoc(@1, ast));
}
| INTERFACE ignore_doc_comments
{
// "interface" is a synonym of android.hidl.base@1.0::IBase
- $$ = new Reference<Type>(gIBaseFqName, convertYYLoc(@1, ast));
+ $$ = new Reference<Type>("interface", gIBaseFqName, convertYYLoc(@1, ast));
}
;
@@ -1162,7 +1162,7 @@ type_or_inplace_compound_declaration
: type { $$ = $1; }
| annotated_compound_declaration ignore_doc_comments
{
- $$ = new Reference<Type>($1, convertYYLoc(@1, ast));
+ $$ = new Reference<Type>($1->definedName(), $1, convertYYLoc(@1, ast));
}
;
diff --git a/host_utils/Formatter.cpp b/host_utils/Formatter.cpp
index 534e8cdc..2268e30c 100644
--- a/host_utils/Formatter.cpp
+++ b/host_utils/Formatter.cpp
@@ -19,6 +19,7 @@
#include <assert.h>
#include <android-base/logging.h>
+#include <vector>
namespace android {
@@ -123,7 +124,7 @@ Formatter &Formatter::operator<<(const std::string &out) {
if (pos == std::string::npos) {
if (mAtStartOfLine) {
- fprintf(mFile, "%*s", (int)(mSpacesPerIndent * mIndentDepth), "");
+ fprintf(mFile, "%*s", (int)(getIndentation()), "");
fprintf(mFile, "%s", mLinePrefix.c_str());
mAtStartOfLine = false;
}
@@ -133,7 +134,7 @@ Formatter &Formatter::operator<<(const std::string &out) {
}
if (mAtStartOfLine && (pos > start || !mLinePrefix.empty())) {
- fprintf(mFile, "%*s", (int)(mSpacesPerIndent * mIndentDepth), "");
+ fprintf(mFile, "%*s", (int)(getIndentation()), "");
fprintf(mFile, "%s", mLinePrefix.c_str());
}
@@ -151,6 +152,56 @@ Formatter &Formatter::operator<<(const std::string &out) {
return *this;
}
+Formatter& Formatter::operator<<(const WrappedOutput& wrappedOutput) {
+ CHECK(mAtStartOfLine) << "This function should only be called at the start of a new line";
+
+ size_t currentPosition = getIndentation();
+ std::function<void(Formatter&, const WrappedOutput::Block&)> printBlock =
+ [&](Formatter& out, const WrappedOutput::Block& block) {
+ size_t blockSize = block.computeSize(false);
+ if (blockSize + currentPosition < wrappedOutput.mLineLength) {
+ block.print(out, false);
+ currentPosition += blockSize;
+ return;
+ }
+
+ // Everything will not fit on this line. Try to fit it on the next line.
+ blockSize = block.computeSize(true);
+ if (blockSize + getIndentation() + mSpacesPerIndent < wrappedOutput.mLineLength) {
+ out << "\n";
+ out.indent();
+
+ block.print(out, true);
+ currentPosition = getIndentation() + blockSize;
+
+ out.unindent();
+ return;
+ }
+
+ if (!block.content.empty()) {
+ // Doesn't have subblocks. This means that the block itself is too big.
+ // Have to print it out.
+ out << "\n";
+ out.indent();
+
+ block.print(out, true);
+ currentPosition = getIndentation() + blockSize;
+
+ out.unindent();
+ return;
+ }
+
+ // Everything will not fit on this line. Go through all the children
+ for (const WrappedOutput::Block& subBlock : block.blocks) {
+ printBlock(out, subBlock);
+ }
+ };
+
+ printBlock(*this, wrappedOutput.mRootBlock);
+
+ return *this;
+}
+
// NOLINT to suppress missing parentheses warning about __type__.
#define FORMATTER_INPUT_INTEGER(__type__) \
Formatter& Formatter::operator<<(__type__ n) { /* NOLINT */ \
@@ -187,10 +238,101 @@ bool Formatter::isValid() const {
return mFile != nullptr;
}
+size_t Formatter::getIndentation() const {
+ return mSpacesPerIndent * mIndentDepth;
+}
+
void Formatter::output(const std::string &text) const {
CHECK(isValid());
fprintf(mFile, "%s", text.c_str());
}
+WrappedOutput::Block::Block(const std::string& content, Block* const parent)
+ : content(content), parent(parent) {}
+
+size_t WrappedOutput::Block::computeSize(bool wrapped) const {
+ CHECK(content.empty() || blocks.empty());
+
+ // There is a wrap, so the block would not be printed
+ if (printUnlessWrapped && wrapped) return 0;
+
+ size_t size = content.size();
+ for (auto block = blocks.begin(); block != blocks.end(); ++block) {
+ if (block == blocks.begin()) {
+ // Only the first one can be wrapped (since content.empty())
+ size += block->computeSize(wrapped);
+ } else {
+ size += block->computeSize(false);
+ }
+ }
+
+ return size;
+}
+
+void WrappedOutput::Block::print(Formatter& out, bool wrapped) const {
+ CHECK(content.empty() || blocks.empty());
+
+ // There is a wrap, so the block should not be printed
+ if (printUnlessWrapped && wrapped) return;
+
+ out << content;
+ for (auto block = blocks.begin(); block != blocks.end(); ++block) {
+ if (block == blocks.begin()) {
+ // Only the first one can be wrapped (since content.empty())
+ block->print(out, wrapped);
+ } else {
+ block->print(out, false);
+ }
+ }
+}
+
+WrappedOutput::WrappedOutput(size_t lineLength)
+ : mLineLength(lineLength), mRootBlock(Block("", nullptr)) {
+ mCurrentBlock = &mRootBlock;
+}
+
+WrappedOutput& WrappedOutput::operator<<(const std::string& str) {
+ std::vector<Block>& blockVec = mCurrentBlock->blocks;
+ if (!blockVec.empty()) {
+ Block& last = blockVec.back();
+ if (!last.populated && last.blocks.empty()) {
+ last.content += str;
+
+ return *this;
+ }
+ }
+
+ blockVec.emplace_back(str, mCurrentBlock);
+ return *this;
+}
+
+WrappedOutput& WrappedOutput::printUnlessWrapped(const std::string& str) {
+ std::vector<Block>& blockVec = mCurrentBlock->blocks;
+ if (!blockVec.empty()) {
+ blockVec.back().populated = true;
+ }
+
+ blockVec.emplace_back(str, mCurrentBlock);
+ blockVec.back().populated = true;
+ blockVec.back().printUnlessWrapped = true;
+
+ return *this;
+}
+
+void WrappedOutput::group(const std::function<void(void)>& block) {
+ std::vector<Block>& blockVec = mCurrentBlock->blocks;
+ if (!blockVec.empty()) {
+ blockVec.back().populated = true;
+ }
+
+ blockVec.emplace_back("", mCurrentBlock);
+ mCurrentBlock = &blockVec.back();
+
+ block();
+
+ mCurrentBlock->populated = true;
+ mCurrentBlock = mCurrentBlock->parent;
+}
+
} // namespace android
diff --git a/host_utils/include/hidl-util/Formatter.h b/host_utils/include/hidl-util/Formatter.h
index bdb89be4..5ce23511 100644
--- a/host_utils/include/hidl-util/Formatter.h
+++ b/host_utils/include/hidl-util/Formatter.h
@@ -20,9 +20,47 @@
#include <functional>
#include <string>
+#include <vector>
namespace android {
+struct Formatter;
+
+struct WrappedOutput {
+ WrappedOutput(size_t lineLength);
+
+ void group(const std::function<void(void)>& block);
+ WrappedOutput& operator<<(const std::string& str);
+ WrappedOutput& printUnlessWrapped(const std::string& str);
+
+ private:
+ struct Block {
+ Block(const std::string& content, Block* const parent);
+
+ // populated helps indicate if we are done filling up the Block.
+ // this allows WrappedOutput to keep adding content to this block
+ // till it is determined that it is full.
+ bool populated = false;
+ bool printUnlessWrapped = false;
+
+ // Only one of content or blocks can have content.
+ std::string content;
+ std::vector<Block> blocks;
+
+ Block* const parent;
+
+ size_t computeSize(bool wrapped) const;
+ void print(Formatter& out, bool wrapped) const;
+ };
+
+ size_t mLineLength;
+
+ Block mRootBlock;
+ Block* mCurrentBlock;
+
+ friend struct Formatter;
+};
+
// Two styles to use a Formatter.
// One is with .indent() calls and operator<<.
// out << "if (good) {\n"; out.indent(); out << "blah\nblah\n"; out.unindent(); out << "}\n";
@@ -128,6 +166,9 @@ struct Formatter {
Formatter &operator<<(double c);
Formatter &operator<<(long double c);
+ // This assumes that the formatter is currently on a newline
+ Formatter& operator<<(const WrappedOutput& wrappedOutput);
+
// Puts a prefix before each line. This is useful if
// you want to start a // comment block, for example.
// The prefix will be put before the indentation.
@@ -137,8 +178,9 @@ struct Formatter {
void unsetLinePrefix();
bool isValid() const;
+ size_t getIndentation() const;
- private:
+ private:
// Creates an invalid formatter object.
Formatter();
diff --git a/main.cpp b/main.cpp
index 27151d67..2a13fffb 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1283,6 +1283,21 @@ static const std::vector<OutputHandler> kFormats = {
},
},
},
+ {
+ "format",
+ "Reformats the .hal files",
+ OutputMode::NEEDS_SRC,
+ Coordinator::Location::PACKAGE_ROOT,
+ GenerationGranularity::PER_FILE,
+ validateForSource,
+ {
+ {
+ FileGenerator::alwaysGenerate,
+ [](const FQName& fqName) { return fqName.name() + ".hal"; },
+ astGenerationFunction(&AST::generateFormattedHidl),
+ },
+ }
+ },
};
// clang-format on
diff --git a/utils/FQName.cpp b/utils/FQName.cpp
index efa835ac..dd191c60 100644
--- a/utils/FQName.cpp
+++ b/utils/FQName.cpp
@@ -160,6 +160,31 @@ bool FQName::setTo(const std::string &s) {
return !invalid;
}
+std::string FQName::getRelativeFQName(const FQName& relativeTo) const {
+ if (relativeTo.mPackage != mPackage) {
+ return string();
+ }
+
+ // Package is the same
+ std::string out;
+ if (relativeTo.version() != version()) {
+ out.append(atVersion());
+ if (!mName.empty() && !version().empty()) {
+ out.append("::");
+ }
+ }
+
+ if (!mName.empty()) {
+ out.append(mName);
+ if (!mValueName.empty()) {
+ out.append(":");
+ out.append(mValueName);
+ }
+ }
+
+ return out;
+}
+
const std::string& FQName::package() const {
return mPackage;
}
diff --git a/utils/include/hidl-util/FQName.h b/utils/include/hidl-util/FQName.h
index 416340a3..9d903026 100644
--- a/utils/include/hidl-util/FQName.h
+++ b/utils/include/hidl-util/FQName.h
@@ -108,6 +108,13 @@ struct FQName {
bool operator==(const FQName &other) const;
bool operator!=(const FQName &other) const;
+ // Provides the FQName relative to "relativeTo"
+ // If this is android.hardware.foo@1.0::IFoo it returns
+ // relativeTo: android.hardware.foo@1.0::IBar - IFoo
+ // relativeTo: android.hardware.foo@1.2::IFoo - @1.0::IFoo
+ // relativeTo: android.hardware.bar@1.0::IFoo - android.hardware.foo@1.0::IFoo
+ std::string getRelativeFQName(const FQName& relativeTo) const;
+
// Must be called on an interface
// android.hardware.foo@1.0::IBar
// -> Bar