1 /*
2  * Copyright (C) 2019 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 <vector>
18 
19 #include "AST.h"
20 #include "CompoundType.h"
21 #include "Lint.h"
22 #include "LintRegistry.h"
23 #include "Location.h"
24 #include "Type.h"
25 
26 namespace android {
27 
checkSmallStructs(const AST & ast,std::vector<Lint> * errors)28 static void checkSmallStructs(const AST& ast, std::vector<Lint>* errors) {
29     // Should lint if it contains a union type at any level
30     std::unordered_set<const Type*> visited;
31     ast.getRootScope().recursivePass(
32             Type::ParseStage::COMPLETED,
33             [&](const Type* type) -> status_t {
34                 if (!type->isCompoundType()) return OK;
35 
36                 const CompoundType* compoundType = static_cast<const CompoundType*>(type);
37 
38                 // Will lint in the file that contains it
39                 if (!Location::inSameFile(compoundType->location(),
40                                           ast.getRootScope().location())) {
41                     return OK;
42                 }
43 
44                 if (compoundType->getReferences().size() == 0) {
45                     errors->push_back(
46                             Lint(ERROR, compoundType->location())
47                             << compoundType->typeName() << " contains no elements.\n"
48                             << "Prefer using android.hidl.safe_union@1.0::Monostate instead.\n");
49                 } else if (compoundType->getReferences().size() == 1) {
50                     errors->push_back(Lint(ERROR, compoundType->location())
51                                       << compoundType->typeName() << " only contains 1 element.\n"
52                                       << "Prefer using the type directly since wrapping it adds "
53                                       << "memory and performance overhead.\n");
54                 }
55 
56                 return OK;
57             },
58             &visited);
59 }
60 
61 REGISTER_LINT(checkSmallStructs);
62 
63 }  // namespace android