You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
301 lines
9.0 KiB
301 lines
9.0 KiB
/* |
|
* 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. |
|
*/ |
|
|
|
#include "Method.h" |
|
|
|
#include "Annotation.h" |
|
#include "ConstantExpression.h" |
|
#include "ScalarType.h" |
|
#include "Type.h" |
|
|
|
#include <android-base/logging.h> |
|
#include <hidl-util/Formatter.h> |
|
#include <algorithm> |
|
|
|
namespace android { |
|
|
|
Method::Method(const char* name, std::vector<NamedReference<Type>*>* args, |
|
std::vector<NamedReference<Type>*>* results, bool oneway, |
|
std::vector<Annotation*>* annotations, const Location& location) |
|
: mName(name), |
|
mArgs(args), |
|
mResults(results), |
|
mOneway(oneway), |
|
mAnnotations(annotations), |
|
mLocation(location) {} |
|
|
|
void Method::fillImplementation( |
|
size_t serial, |
|
MethodImpl cppImpl, |
|
MethodImpl javaImpl) { |
|
mIsHidlReserved = true; |
|
mSerial = serial; |
|
mCppImpl = cppImpl; |
|
mJavaImpl = javaImpl; |
|
|
|
CHECK(mJavaImpl.find(IMPL_STUB_IMPL) == mJavaImpl.end()) |
|
<< "FATAL: mJavaImpl should not use IMPL_STUB_IMPL; use IMPL_INTERFACE instead."; |
|
CHECK(mCppImpl.find(IMPL_STUB_IMPL) == mCppImpl.end() || |
|
mCppImpl.find(IMPL_STUB) == mCppImpl.end()) |
|
<< "FATAL: mCppImpl IMPL_STUB will override IMPL_STUB_IMPL."; |
|
} |
|
|
|
std::string Method::name() const { |
|
return mName; |
|
} |
|
|
|
const std::vector<NamedReference<Type>*>& Method::args() const { |
|
return *mArgs; |
|
} |
|
|
|
const std::vector<NamedReference<Type>*>& Method::results() const { |
|
return *mResults; |
|
} |
|
|
|
const std::vector<Annotation *> &Method::annotations() const { |
|
return *mAnnotations; |
|
} |
|
|
|
std::vector<Reference<Type>*> Method::getReferences() { |
|
const auto& constRet = static_cast<const Method*>(this)->getReferences(); |
|
std::vector<Reference<Type>*> ret(constRet.size()); |
|
std::transform(constRet.begin(), constRet.end(), ret.begin(), |
|
[](const auto* ref) { return const_cast<Reference<Type>*>(ref); }); |
|
return ret; |
|
} |
|
|
|
std::vector<const Reference<Type>*> Method::getReferences() const { |
|
std::vector<const Reference<Type>*> ret; |
|
ret.insert(ret.end(), mArgs->begin(), mArgs->end()); |
|
ret.insert(ret.end(), mResults->begin(), mResults->end()); |
|
return ret; |
|
} |
|
|
|
std::vector<Reference<Type>*> Method::getStrongReferences() { |
|
const auto& constRet = static_cast<const Method*>(this)->getStrongReferences(); |
|
std::vector<Reference<Type>*> ret(constRet.size()); |
|
std::transform(constRet.begin(), constRet.end(), ret.begin(), |
|
[](const auto* ref) { return const_cast<Reference<Type>*>(ref); }); |
|
return ret; |
|
} |
|
|
|
std::vector<const Reference<Type>*> Method::getStrongReferences() const { |
|
std::vector<const Reference<Type>*> ret; |
|
for (const auto* ref : getReferences()) { |
|
if (!ref->shallowGet()->isNeverStrongReference()) { |
|
ret.push_back(ref); |
|
} |
|
} |
|
return ret; |
|
} |
|
|
|
std::vector<ConstantExpression*> Method::getConstantExpressions() { |
|
const auto& constRet = static_cast<const Method*>(this)->getConstantExpressions(); |
|
std::vector<ConstantExpression*> ret(constRet.size()); |
|
std::transform(constRet.begin(), constRet.end(), ret.begin(), |
|
[](const auto* ce) { return const_cast<ConstantExpression*>(ce); }); |
|
return ret; |
|
} |
|
|
|
std::vector<const ConstantExpression*> Method::getConstantExpressions() const { |
|
std::vector<const ConstantExpression*> ret; |
|
for (const auto* annotation : *mAnnotations) { |
|
const auto& retAnnotation = annotation->getConstantExpressions(); |
|
ret.insert(ret.end(), retAnnotation.begin(), retAnnotation.end()); |
|
} |
|
return ret; |
|
} |
|
|
|
void Method::cppImpl(MethodImplType type, Formatter &out) const { |
|
CHECK(mIsHidlReserved); |
|
auto it = mCppImpl.find(type); |
|
if (it != mCppImpl.end()) { |
|
if (it->second != nullptr) { |
|
it->second(out); |
|
} |
|
} |
|
} |
|
|
|
void Method::javaImpl(MethodImplType type, Formatter &out) const { |
|
CHECK(mIsHidlReserved); |
|
auto it = mJavaImpl.find(type); |
|
if (it != mJavaImpl.end()) { |
|
if (it->second != nullptr) { |
|
it->second(out); |
|
} |
|
} |
|
} |
|
|
|
bool Method::overridesCppImpl(MethodImplType type) const { |
|
CHECK(mIsHidlReserved); |
|
return mCppImpl.find(type) != mCppImpl.end(); |
|
} |
|
|
|
bool Method::overridesJavaImpl(MethodImplType type) const { |
|
CHECK(mIsHidlReserved); |
|
return mJavaImpl.find(type) != mJavaImpl.end(); |
|
} |
|
|
|
Method* Method::copySignature() const { |
|
Method* method = new Method(mName.c_str(), mArgs, mResults, mOneway, mAnnotations, location()); |
|
method->setDocComment(getDocComment()); |
|
return method; |
|
} |
|
|
|
void Method::setSerialId(size_t serial) { |
|
CHECK(!mIsHidlReserved); |
|
mSerial = serial; |
|
} |
|
|
|
size_t Method::getSerialId() const { |
|
return mSerial; |
|
} |
|
|
|
bool Method::hasEmptyCppArgSignature() const { |
|
return args().empty() && (results().empty() || canElideCallback() != nullptr); |
|
} |
|
|
|
void Method::generateCppReturnType(Formatter &out, bool specifyNamespaces) const { |
|
const NamedReference<Type>* elidedReturn = canElideCallback(); |
|
const std::string space = (specifyNamespaces ? "::android::hardware::" : ""); |
|
|
|
if (elidedReturn == nullptr) { |
|
out << space << "Return<void> "; |
|
} else { |
|
out << space |
|
<< "Return<" |
|
<< elidedReturn->type().getCppResultType( specifyNamespaces) |
|
<< "> "; |
|
} |
|
} |
|
|
|
void Method::generateCppSignature(Formatter &out, |
|
const std::string &className, |
|
bool specifyNamespaces) const { |
|
generateCppReturnType(out, specifyNamespaces); |
|
|
|
if (!className.empty()) { |
|
out << className << "::"; |
|
} |
|
|
|
out << name() |
|
<< "("; |
|
emitCppArgSignature(out, specifyNamespaces); |
|
out << ")"; |
|
} |
|
|
|
static void emitCppArgResultSignature(Formatter& out, |
|
const std::vector<NamedReference<Type>*>& args, |
|
bool specifyNamespaces) { |
|
out.join(args.begin(), args.end(), ", ", [&](auto arg) { |
|
out << arg->type().getCppArgumentType(specifyNamespaces); |
|
out << " "; |
|
out << arg->name(); |
|
}); |
|
} |
|
|
|
static void emitJavaArgResultSignature(Formatter& out, |
|
const std::vector<NamedReference<Type>*>& args) { |
|
out.join(args.begin(), args.end(), ", ", [&](auto arg) { |
|
out << arg->type().getJavaType(); |
|
out << " "; |
|
out << arg->name(); |
|
}); |
|
} |
|
|
|
void Method::emitCppArgSignature(Formatter &out, bool specifyNamespaces) const { |
|
emitCppArgResultSignature(out, args(), specifyNamespaces); |
|
|
|
const bool returnsValue = !results().empty(); |
|
const NamedReference<Type>* elidedReturn = canElideCallback(); |
|
if (returnsValue && elidedReturn == nullptr) { |
|
if (!args().empty()) { |
|
out << ", "; |
|
} |
|
|
|
out << name() << "_cb _hidl_cb"; |
|
} |
|
} |
|
void Method::emitCppResultSignature(Formatter &out, bool specifyNamespaces) const { |
|
emitCppArgResultSignature(out, results(), specifyNamespaces); |
|
} |
|
void Method::emitJavaArgSignature(Formatter &out) const { |
|
emitJavaArgResultSignature(out, args()); |
|
} |
|
void Method::emitJavaResultSignature(Formatter &out) const { |
|
emitJavaArgResultSignature(out, results()); |
|
} |
|
|
|
void Method::dumpAnnotations(Formatter &out) const { |
|
if (mAnnotations->size() == 0) { |
|
return; |
|
} |
|
|
|
out << "// "; |
|
for (size_t i = 0; i < mAnnotations->size(); ++i) { |
|
if (i > 0) { |
|
out << " "; |
|
} |
|
mAnnotations->at(i)->dump(out); |
|
} |
|
out << "\n"; |
|
} |
|
|
|
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); })) { |
|
return false; |
|
} |
|
|
|
if (!std::all_of(mResults->begin(), mResults->end(), |
|
[&](const auto* arg) { return (*arg)->isJavaCompatible(visited); })) { |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
const NamedReference<Type>* Method::canElideCallback() const { |
|
// Can't elide callback for void or tuple-returning methods |
|
if (mResults->size() != 1) { |
|
return nullptr; |
|
} |
|
|
|
const NamedReference<Type>* typedVar = mResults->at(0); |
|
|
|
if (typedVar->type().isElidableType()) { |
|
return typedVar; |
|
} |
|
|
|
return nullptr; |
|
} |
|
|
|
const Location& Method::location() const { |
|
return mLocation; |
|
} |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
|
|
bool TypedVarVector::add(NamedReference<Type>* v) { |
|
if (mNames.emplace(v->name()).second) { |
|
push_back(v); |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
} // namespace android |
|
|
|
|