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 26using android::base::StringPrintf; 27using android::base::Split; 28using android::base::Trim; 29using std::string; 30using std::vector; 31 32namespace android { 33namespace aidl { 34 35// Since packages cannot contain '-' normally, we cannot be asked 36// to create a type that conflicts with these strings. 37const char kAidlReservedTypePackage[] = "aidl-internal"; 38const char kUtf8StringClass[] = "Utf8String"; 39const char kUtf8InCppStringClass[] = "Utf8InCppString"; 40 41// These *must* match the package and class names above. 42const char kUtf8StringCanonicalName[] = "aidl-internal.Utf8String"; 43const char kUtf8InCppStringCanonicalName[] = "aidl-internal.Utf8InCppString"; 44 45const char kStringCanonicalName[] = "java.lang.String"; 46 47const char kUtf8Annotation[] = "@utf8"; 48const char kUtf8InCppAnnotation[] = "@utfInCpp"; 49 50namespace { 51 52bool 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 72ValidatableType::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 82string 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 96bool TypeNamespace::IsValidPackage(const string& /* package */) const { 97 return true; 98} 99 100const ValidatableType* TypeNamespace::GetReturnType( 101 const AidlType& raw_type, const string& filename, 102 const AidlInterface& interface) const { 103 string error_msg; 104 const ValidatableType* return_type = GetValidatableType(raw_type, &error_msg, 105 interface); 106 if (return_type == nullptr) { 107 LOG(ERROR) << StringPrintf("In file %s line %d return type %s:\n ", 108 filename.c_str(), raw_type.GetLine(), 109 raw_type.ToString().c_str()) 110 << error_msg; 111 return nullptr; 112 } 113 114 return return_type; 115} 116 117const ValidatableType* TypeNamespace::GetArgType( 118 const AidlArgument& a, int arg_index, const string& filename, 119 const AidlInterface& interface) const { 120 string error_prefix = StringPrintf( 121 "In file %s line %d parameter %s (argument %d):\n ", 122 filename.c_str(), a.GetLine(), a.GetName().c_str(), arg_index); 123 124 // check the arg type 125 string error_msg; 126 const ValidatableType* t = GetValidatableType(a.GetType(), &error_msg, 127 interface); 128 if (t == nullptr) { 129 LOG(ERROR) << error_prefix << error_msg; 130 return nullptr; 131 } 132 133 if (!a.DirectionWasSpecified() && t->CanBeOutParameter()) { 134 LOG(ERROR) << error_prefix << StringPrintf( 135 "'%s' can be an out type, so you must declare it as in," 136 " out or inout.", 137 a.GetType().ToString().c_str()); 138 return nullptr; 139 } 140 141 if (a.GetDirection() != AidlArgument::IN_DIR && 142 !t->CanBeOutParameter()) { 143 LOG(ERROR) << error_prefix << StringPrintf( 144 "'%s' can only be an in parameter.", 145 a.ToString().c_str()); 146 return nullptr; 147 } 148 149 // check that the name doesn't match a keyword 150 if (is_java_keyword(a.GetName().c_str())) { 151 LOG(ERROR) << error_prefix << "Argument name is a Java or aidl keyword"; 152 return nullptr; 153 } 154 155 // Reserve a namespace for internal use 156 if (a.GetName().substr(0, 5) == "_aidl") { 157 LOG(ERROR) << error_prefix << "Argument name cannot begin with '_aidl'"; 158 return nullptr; 159 } 160 161 return t; 162} 163 164} // namespace aidl 165} // namespace android 166