Merge "Add lint for compound types containing < 2 fields"
diff --git a/lint/lints/emptyStructs.cpp b/lint/lints/emptyStructs.cpp
new file mode 100644
index 0000000..f95d55b
--- /dev/null
+++ b/lint/lints/emptyStructs.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 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 <vector>
+
+#include "AST.h"
+#include "CompoundType.h"
+#include "Lint.h"
+#include "LintRegistry.h"
+#include "Location.h"
+#include "Type.h"
+
+namespace android {
+
+static void checkSmallStructs(const AST& ast, std::vector<Lint>* errors) {
+ // Should lint if it contains a union type at any level
+ std::unordered_set<const Type*> visited;
+ ast.getRootScope().recursivePass(
+ Type::ParseStage::COMPLETED,
+ [&](const Type* type) -> status_t {
+ if (!type->isCompoundType()) return OK;
+
+ const CompoundType* compoundType = static_cast<const CompoundType*>(type);
+
+ // Will lint in the file that contains it
+ if (!Location::inSameFile(compoundType->location(),
+ ast.getRootScope().location())) {
+ return OK;
+ }
+
+ if (compoundType->getReferences().size() == 0) {
+ errors->push_back(
+ Lint(ERROR, compoundType->location())
+ << compoundType->typeName() << " contains no elements.\n"
+ << "Prefer using android.hidl.safe_union@1.0::Monostate instead.");
+ } else if (compoundType->getReferences().size() == 1) {
+ errors->push_back(Lint(ERROR, compoundType->location())
+ << compoundType->typeName() << " only contains 1 element.\n"
+ << "Prefer using the type directly since wrapping it adds "
+ << "memory and performance overhead.");
+ }
+
+ return OK;
+ },
+ &visited);
+}
+
+REGISTER_LINT(checkSmallStructs);
+
+} // namespace android
\ No newline at end of file
diff --git a/lint/test/interfaces/import_types/1.1/types.hal b/lint/test/interfaces/import_types/1.1/types.hal
index 723c35e..ada4f67 100644
--- a/lint/test/interfaces/import_types/1.1/types.hal
+++ b/lint/test/interfaces/import_types/1.1/types.hal
@@ -20,4 +20,5 @@
struct ContainsFoo {
Foo fooInstance;
+ uint8_t preventLintForSingleElement;
};
\ No newline at end of file
diff --git a/lint/test/interfaces/safeunion/1.0/IUnionInStruct.hal b/lint/test/interfaces/safeunion/1.0/IUnionInStruct.hal
index f2e3a82..654c280 100644
--- a/lint/test/interfaces/safeunion/1.0/IUnionInStruct.hal
+++ b/lint/test/interfaces/safeunion/1.0/IUnionInStruct.hal
@@ -22,5 +22,6 @@
uint8_t number;
int32_t otherNumber;
} shouldOnlyLintDefinition;
+ uint8_t preventLintForSingleElement;
};
};
\ No newline at end of file
diff --git a/lint/test/interfaces/safeunion/1.1/types.hal b/lint/test/interfaces/safeunion/1.1/types.hal
index 6653cfb..f261834 100644
--- a/lint/test/interfaces/safeunion/1.1/types.hal
+++ b/lint/test/interfaces/safeunion/1.1/types.hal
@@ -20,4 +20,5 @@
struct SomeStruct {
InTypes unionType;
+ uint8_t preventLintForSingleElement;
};
\ No newline at end of file
diff --git a/lint/test/interfaces/small_structs/1.0/IEmptyStruct.hal b/lint/test/interfaces/small_structs/1.0/IEmptyStruct.hal
new file mode 100644
index 0000000..12255a2
--- /dev/null
+++ b/lint/test/interfaces/small_structs/1.0/IEmptyStruct.hal
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package lint_test.small_structs@1.0;
+
+interface IEmptyStruct {
+ struct EmptyStruct {};
+};
\ No newline at end of file
diff --git a/lint/test/interfaces/small_structs/1.0/IEmptyUnion.hal b/lint/test/interfaces/small_structs/1.0/IEmptyUnion.hal
new file mode 100644
index 0000000..cbcb49f
--- /dev/null
+++ b/lint/test/interfaces/small_structs/1.0/IEmptyUnion.hal
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package lint_test.small_structs@1.0;
+
+interface IEmptyUnion {
+ union EmptyUnion {};
+};
\ No newline at end of file
diff --git a/lint/test/interfaces/small_structs/1.0/IReference.hal b/lint/test/interfaces/small_structs/1.0/IReference.hal
new file mode 100644
index 0000000..2496b30
--- /dev/null
+++ b/lint/test/interfaces/small_structs/1.0/IReference.hal
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package lint_test.small_structs@1.0;
+
+import ISingleStruct.SingleStruct;
+import IEmptyStruct.EmptyStruct;
+
+interface IReference {
+ referenceBadStruct(SingleStruct sStruct) generates (EmptyStruct eStruct);
+};
\ No newline at end of file
diff --git a/lint/test/interfaces/small_structs/1.0/ISingleStruct.hal b/lint/test/interfaces/small_structs/1.0/ISingleStruct.hal
new file mode 100644
index 0000000..61b0663
--- /dev/null
+++ b/lint/test/interfaces/small_structs/1.0/ISingleStruct.hal
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package lint_test.small_structs@1.0;
+
+interface ISingleStruct {
+ struct SingleStruct {
+ uint8_t singleField;
+ };
+};
\ No newline at end of file
diff --git a/lint/test/interfaces/small_structs/1.0/ISingleUnion.hal b/lint/test/interfaces/small_structs/1.0/ISingleUnion.hal
new file mode 100644
index 0000000..4d5874c
--- /dev/null
+++ b/lint/test/interfaces/small_structs/1.0/ISingleUnion.hal
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package lint_test.small_structs@1.0;
+
+interface ISingleUnion {
+ union SingleUnion {
+ uint8_t singleField;
+ };
+};
\ No newline at end of file
diff --git a/lint/test/main.cpp b/lint/test/main.cpp
index e72ff54..0dfb8f1 100644
--- a/lint/test/main.cpp
+++ b/lint/test/main.cpp
@@ -25,7 +25,9 @@
#include "../LintRegistry.h"
#include "Coordinator.h"
+using ::testing::Contains;
using ::testing::ContainsRegex;
+using ::testing::Property;
namespace android {
class HidlLintTest : public ::testing::Test {
@@ -82,6 +84,15 @@
EXPECT_THAT(errors[0].getMessage(), ContainsRegex(errorMsg)); \
} while (false)
+#define EXPECT_A_LINT(interface, errorMsg) \
+ do { \
+ std::vector<Lint> errors; \
+ getLintsForHal(interface, &errors); \
+ EXPECT_LE(1, errors.size()); \
+ if (errors.size() < 1) break; \
+ EXPECT_THAT(errors, Contains(Property(&Lint::getMessage, ContainsRegex(errorMsg)))); \
+ } while (false)
+
TEST_F(HidlLintTest, OnewayLintTest) {
// Has no errors (empty). Lint size should be 0.
EXPECT_NO_LINT("lint_test.oneway@1.0::IEmpty");
@@ -152,4 +163,17 @@
// Imports types.hal from same package with fully qualified name
EXPECT_LINT("lint_test.import_types@1.1::IImport", "Redundant import");
}
+
+TEST_F(HidlLintTest, SmallStructsTest) {
+ // Referencing bad structs should not lint
+ EXPECT_NO_LINT("lint_test.small_structs@1.0::IReference");
+
+ // Empty structs/unions should lint
+ EXPECT_LINT("lint_test.small_structs@1.0::IEmptyStruct", "contains no elements");
+ EXPECT_A_LINT("lint_test.small_structs@1.0::IEmptyUnion", "contains no elements");
+
+ // Structs/unions with single field should lint
+ EXPECT_LINT("lint_test.small_structs@1.0::ISingleStruct", "only contains 1 element");
+ EXPECT_A_LINT("lint_test.small_structs@1.0::ISingleUnion", "only contains 1 element");
+}
} // namespace android
\ No newline at end of file