1 /* 2 * Copyright (C) 2015, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "type_namespace.h" 18 19 #include <algorithm> 20 #include <string> 21 #include <vector> 22 23 #include "aidl_language.h" 24 #include "logging.h" 25 26 using android::base::StringPrintf; 27 using android::base::Split; 28 using android::base::Trim; 29 using std::string; 30 using std::vector; 31 32 namespace android { 33 namespace aidl { 34 35 // Since packages cannot contain '-' normally, we cannot be asked 36 // to create a type that conflicts with these strings. 37 const char kAidlReservedTypePackage[] = "aidl-internal"; 38 const char kUtf8StringClass[] = "Utf8String"; 39 const char kUtf8InCppStringClass[] = "Utf8InCppString"; 40 41 // These *must* match the package and class names above. 42 const char kUtf8StringCanonicalName[] = "aidl-internal.Utf8String"; 43 const char kUtf8InCppStringCanonicalName[] = "aidl-internal.Utf8InCppString"; 44 45 const char kStringCanonicalName[] = "java.lang.String"; 46 47 const char kUtf8Annotation[] = "@utf8"; 48 const char kUtf8InCppAnnotation[] = "@utfInCpp"; 49 50 namespace { 51 52 bool is_java_keyword(const char* str) { 53 static const std::vector<std::string> kJavaKeywords{ 54 "abstract", "assert", "boolean", "break", "byte", 55 "case", "catch", "char", "class", "const", 56 "continue", "default", "do", "double", "else", 57 "enum", "extends", "final", "finally", "float", 58 "for", "goto", "if", "implements", "import", 59 "instanceof", "int", "interface", "long", "native", 60 "new", "package", "private", "protected", "public", 61 "return", "short", "static", "strictfp", "super", 62 "switch", "synchronized", "this", "throw", "throws", 63 "transient", "try", "void", "volatile", "while", 64 "true", "false", "null", 65 }; 66 return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != 67 kJavaKeywords.end(); 68 } 69 70 } // namespace 71 72 ValidatableType::ValidatableType( 73 int kind, const string& package, const string& type_name, 74 const string& decl_file, int decl_line) 75 : kind_(kind), 76 type_name_(type_name), 77 canonical_name_((package.empty()) ? type_name 78 : package + "." + type_name), 79 origin_file_(decl_file), 80 origin_line_(decl_line) {} 81 82 string ValidatableType::HumanReadableKind() const { 83 switch (Kind()) { 84 case ValidatableType::KIND_BUILT_IN: 85 return "a built in"; 86 case ValidatableType::KIND_PARCELABLE: 87 return "a parcelable"; 88 case ValidatableType::KIND_INTERFACE: 89 return "an interface"; 90 case ValidatableType::KIND_GENERATED: 91 return "a generated"; 92 } 93 return "unknown"; 94 } 95 96 bool TypeNamespace::IsValidPackage(const string& /* package */) const { 97 return true; 98 } 99 100 const ValidatableType* TypeNamespace::GetReturnType( 101 const AidlType& raw_type, const string& filename) const { 102 string error_msg; 103 const ValidatableType* return_type = GetValidatableType(raw_type, &error_msg); 104 if (return_type == nullptr) { 105 LOG(ERROR) << StringPrintf("In file %s line %d return type %s:\n ", 106 filename.c_str(), raw_type.GetLine(), 107 raw_type.ToString().c_str()) 108 << error_msg; 109 return nullptr; 110 } 111 112 return return_type; 113 } 114 115 const ValidatableType* TypeNamespace::GetArgType( 116 const AidlArgument& a, int arg_index, const string& filename) const { 117 string error_prefix = StringPrintf( 118 "In file %s line %d parameter %s (argument %d):\n ", 119 filename.c_str(), a.GetLine(), a.GetName().c_str(), arg_index); 120 121 // check the arg type 122 string error_msg; 123 const ValidatableType* t = GetValidatableType(a.GetType(), &error_msg); 124 if (t == nullptr) { 125 LOG(ERROR) << error_prefix << error_msg; 126 return nullptr; 127 } 128 129 if (!a.DirectionWasSpecified() && t->CanBeOutParameter()) { 130 LOG(ERROR) << error_prefix << StringPrintf( 131 "'%s' can be an out type, so you must declare it as in," 132 " out or inout.", 133 a.GetType().ToString().c_str()); 134 return nullptr; 135 } 136 137 if (a.GetDirection() != AidlArgument::IN_DIR && 138 !t->CanBeOutParameter()) { 139 LOG(ERROR) << error_prefix << StringPrintf( 140 "'%s' can only be an in parameter.", 141 a.ToString().c_str()); 142 return nullptr; 143 } 144 145 // check that the name doesn't match a keyword 146 if (is_java_keyword(a.GetName().c_str())) { 147 LOG(ERROR) << error_prefix << "Argument name is a Java or aidl keyword"; 148 return nullptr; 149 } 150 151 // Reserve a namespace for internal use 152 if (a.GetName().substr(0, 5) == "_aidl") { 153 LOG(ERROR) << error_prefix << "Argument name cannot begin with '_aidl'"; 154 return nullptr; 155 } 156 157 return t; 158 } 159 160 } // namespace aidl 161 } // namespace android 162