blob: 390ffda0a0b7767d8fb56ffa5b92d76d3a1e99d1 [file] [log] [blame]
/*
* 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 TYPE_H_
#define TYPE_H_
#include <android-base/macros.h>
#include <utils/Errors.h>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "DocComment.h"
#include "Reference.h"
namespace android {
struct ConstantExpression;
struct Formatter;
struct FQName;
struct ScalarType;
struct Scope;
struct Type : DocCommentable {
Type(Scope* parent, const std::string& definedName);
virtual ~Type();
virtual bool isArray() const;
virtual bool isBitField() const;
virtual bool isCompoundType() const;
virtual bool isEnum() const;
virtual bool isHandle() const;
virtual bool isInterface() const;
virtual bool isNamedType() const;
virtual bool isMemory() const;
virtual bool isPointer() const;
virtual bool isScope() const;
virtual bool isScalar() const;
virtual bool isString() const;
virtual bool isTemplatedType() const;
virtual bool isTypeDef() const;
virtual bool isVector() const;
virtual bool isFmq() const;
// Resolves the type by unwrapping typedefs
Type* resolve();
virtual const Type* resolve() const;
// All types defined in this type.
std::vector<Type*> getDefinedTypes();
virtual std::vector<const Type*> getDefinedTypes() const;
// All types referenced in this type.
std::vector<Reference<Type>*> getReferences();
virtual std::vector<const Reference<Type>*> getReferences() const;
// All constant expressions referenced in this type.
std::vector<ConstantExpression*> getConstantExpressions();
virtual std::vector<const ConstantExpression*> getConstantExpressions() const;
// All types referenced in this type that must have completed
// definiton before being referenced.
std::vector<Reference<Type>*> getStrongReferences();
virtual std::vector<const Reference<Type>*> getStrongReferences() const;
// Indicate stage of parsing.
enum class ParseStage {
// Indicate that the source file is being parsed and this object is being filled.
PARSE,
// Indicate that all source files are parsed, and program is working on type dependencies
// and validation.
POST_PARSE,
// Indicate that parsing is completed, and program is in code-generation stage.
COMPLETED,
};
// Proceeds recursive pass
// Makes sure to visit each node only once.
// If mParseStage < stage, object is not ready for this recursivePass() call
// yet, and function will return error.
status_t recursivePass(ParseStage stage, const std::function<status_t(Type*)>& func,
std::unordered_set<const Type*>* visited);
status_t recursivePass(ParseStage stage, const std::function<status_t(const Type*)>& func,
std::unordered_set<const Type*>* visited) const;
// Recursive tree pass that completes type declarations
// that depend on super types
virtual status_t resolveInheritance();
// Recursive tree pass that validates all type-related
// syntax restrictions
virtual status_t validate() const;
// Recursive tree pass checkAcyclic return type.
// Stores cycle end for nice error messages.
struct CheckAcyclicStatus {
CheckAcyclicStatus(status_t status, const Type* cycleEnd = nullptr);
status_t status;
// If a cycle is found, stores the end of cycle.
// While going back in recursion, this is used to stop printing the cycle.
const Type* cycleEnd;
};
// Recursive tree pass that ensures that type definitions and references
// are acyclic and builds reversed topological order of the types.
// If some cases allow using of incomplete types, these cases are to be
// declared in Type::getStrongReferences.
CheckAcyclicStatus topologicalOrder(std::unordered_map<const Type*, size_t>* reversedOrder,
std::unordered_set<const Type*>* stack) const;
// Checks following C++ restriction on forward declaration:
// inner struct could be forward declared only inside its parent.
status_t checkForwardReferenceRestrictions(const Reference<Type>& ref) const;
virtual const ScalarType *resolveToScalarType() const;
virtual std::string typeName() const = 0;
bool isValidEnumStorageType() const;
virtual bool isElidableType() const;
virtual bool canCheckEquality() const;
bool canCheckEquality(std::unordered_set<const Type*>* visited) const;
virtual bool deepCanCheckEquality(std::unordered_set<const Type*>* visited) const;
// ParseStage can only be incremented.
ParseStage getParseStage() const;
void setParseStage(ParseStage stage);
Scope* parent();
const Scope* parent() const;
const std::string& definedName() const;
enum StorageMode {
StorageMode_Stack,
StorageMode_Argument,
StorageMode_Result,
};
// specifyNamespaces: whether to specify namespaces for built-in types
virtual std::string getCppType(
StorageMode mode,
bool specifyNamespaces) const;
std::string decorateCppName(
const std::string &name,
StorageMode mode,
bool specifyNamespaces) const;
std::string getCppStackType(bool specifyNamespaces = true) const;
std::string getCppResultType(bool specifyNamespaces = true) const;
std::string getCppArgumentType(bool specifyNamespaces = true) const;
std::string getCppTypeCast(const std::string& objName,
bool specifyNamespaces = true) const;
// For an array type, dimensionality information will be accumulated at the
// end of the returned string.
// if forInitializer == true, actual dimensions are included, i.e. [3][5],
// otherwise (and by default), they are omitted, i.e. [][].
virtual std::string getJavaType(bool forInitializer = false) const;
// Identical to getJavaType() for most types, except: primitives, in which
// case the wrapper type is returned, and generics (such as ArrayList<?>),
// where the type specialization is omitted to facilitate use of
// instanceof or class.isInstance().
virtual std::string getJavaTypeClass() const;
virtual std::string getJavaTypeCast(const std::string& objName) const;
virtual std::string getJavaSuffix() const;
virtual std::string getVtsType() const;
virtual std::string getVtsValueName() const;
enum ErrorMode {
ErrorMode_Goto,
ErrorMode_Break,
ErrorMode_Return,
ErrorMode_ReturnNothing,
};
virtual void emitReaderWriter(
Formatter &out,
const std::string &name,
const std::string &parcelObj,
bool parcelObjIsPointer,
bool isReader,
ErrorMode mode) const;
virtual void emitReaderWriterEmbedded(
Formatter &out,
size_t depth,
const std::string &name,
const std::string &sanitizedName,
bool nameIsPointer,
const std::string &parcelObj,
bool parcelObjIsPointer,
bool isReader,
ErrorMode mode,
const std::string &parentName,
const std::string &offsetText) const;
virtual void emitDump(
Formatter &out,
const std::string &streamName,
const std::string &name) const;
virtual void emitJavaDump(
Formatter &out,
const std::string &streamName,
const std::string &name) const;
virtual void emitJavaReaderWriter(
Formatter &out,
const std::string &parcelObj,
const std::string &argName,
bool isReader) const;
virtual void emitJavaFieldInitializer(
Formatter &out,
const std::string &fieldName) const;
virtual void emitJavaFieldDefaultInitialValue(
Formatter &out,
const std::string &declaredFieldName) const;
virtual void emitJavaFieldReaderWriter(
Formatter &out,
size_t depth,
const std::string &parcelName,
const std::string &blobName,
const std::string &fieldName,
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;
// Emit scope C++ forward declaration.
// There is no need to forward declare interfaces, as
// they are always declared in global scope in dedicated file.
virtual void emitTypeForwardDeclaration(Formatter& out) const;
// Emit any declarations pertaining to this type that have to be
// directly in a namespace, i.e. enum class operators.
// For android.hardware.foo@1.0::*, this will be in namespace
// android::hardware::foo::V1_0
virtual void emitPackageTypeDeclarations(Formatter& out) const;
// Emit any definitions pertaining to this type that have to be
// directly in a namespace. Typically, these are things that are only
// used for a small subset of types, so by putting them in the header,
// the space cost is moved to the small number of clients that use the
// feature.
// For android.hardware.foo@1.0::*, this will be in namespace
// android::hardware::foo::V1_0
virtual void emitPackageTypeHeaderDefinitions(Formatter& out) const;
// Emit any declarations pertaining to this type that have to be
// at global scope for transport, e.g. read/writeEmbeddedTo/FromParcel
// For android.hardware.foo@1.0::*, this will be in namespace
// android::hardware::foo::V1_0
virtual void emitPackageHwDeclarations(Formatter& out) const;
virtual void emitTypeDefinitions(Formatter& out, const std::string& prefix) const;
virtual void emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const;
virtual bool needsEmbeddedReadWrite() const;
virtual bool resultNeedsDeref() const;
// Generates type declaration for vts proto file.
// TODO (b/30844146): make it a pure virtual method.
virtual void emitVtsTypeDeclarations(Formatter& out) const;
// Generates type declaration as attribute of method (return value or method
// argument) or attribute of compound type for vts proto file.
virtual void emitVtsAttributeType(Formatter& out) const;
// Returns true iff this type is supported through the Java backend.
bool isJavaCompatible() const;
bool isJavaCompatible(std::unordered_set<const Type*>* visited) const;
virtual bool deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const;
// Returns true iff type contains pointer
// (excluding methods and inner types).
bool containsPointer() const;
bool containsPointer(std::unordered_set<const Type*>* visited) const;
virtual bool deepContainsPointer(std::unordered_set<const Type*>* visited) const;
virtual void getAlignmentAndSize(size_t *align, size_t *size) const;
virtual void appendToExportedTypesVector(
std::vector<const Type *> *exportedTypes) const;
virtual void emitExportedHeader(Formatter& out, bool forJava) const;
virtual bool isNeverStrongReference() const;
static void handleError(Formatter &out, ErrorMode mode);
protected:
void emitReaderWriterEmbeddedForTypeName(
Formatter &out,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
bool parcelObjIsPointer,
bool isReader,
ErrorMode mode,
const std::string &parentName,
const std::string &offsetText,
const std::string &typeName,
const std::string &childName,
const std::string &funcNamespace) const;
void emitJavaReaderWriterWithSuffix(
Formatter &out,
const std::string &parcelObj,
const std::string &argName,
bool isReader,
const std::string &suffix,
const std::string &extra) const;
void emitDumpWithMethod(
Formatter &out,
const std::string &streamName,
const std::string &methodName,
const std::string &name) const;
// This is the name given to the type in the hidl file
std::string mDefinedName;
private:
ParseStage mParseStage = ParseStage::PARSE;
Scope* const mParent;
DISALLOW_COPY_AND_ASSIGN(Type);
};
struct TemplatedType : public Type {
void setElementType(const Reference<Type>& elementType);
const Type* getElementType() const;
virtual std::string templatedTypeName() const = 0;
std::string typeName() const override;
bool isTemplatedType() const override;
virtual bool isCompatibleElementType(const Type* elementType) const = 0;
std::vector<const Reference<Type>*> getReferences() const override;
virtual status_t validate() const override;
void emitVtsTypeDeclarations(Formatter& out) const override;
void emitVtsAttributeType(Formatter& out) const override;
protected:
TemplatedType(Scope* parent, const std::string& definedName);
Reference<Type> mElementType;
private:
DISALLOW_COPY_AND_ASSIGN(TemplatedType);
};
} // namespace android
#endif // TYPE_H_