diff options
Diffstat (limited to 'tools')
26 files changed, 308 insertions, 145 deletions
diff --git a/tools/aapt/ConfigDescription.h b/tools/aapt/ConfigDescription.h index b4ea624524b3..6e9dc3d9456a 100644 --- a/tools/aapt/ConfigDescription.h +++ b/tools/aapt/ConfigDescription.h @@ -34,8 +34,8 @@ struct ConfigDescription : public android::ResTable_config { size = sizeof(android::ResTable_config); } - ConfigDescription(const ConfigDescription&o) { - *static_cast<android::ResTable_config*>(this) = o; + ConfigDescription(const ConfigDescription&o) + : android::ResTable_config(o) { } ConfigDescription& operator=(const android::ResTable_config& o) { diff --git a/tools/aapt/tests/AaptConfig_test.cpp b/tools/aapt/tests/AaptConfig_test.cpp index 4f22fa581a88..b7c6bd25a565 100644 --- a/tools/aapt/tests/AaptConfig_test.cpp +++ b/tools/aapt/tests/AaptConfig_test.cpp @@ -20,7 +20,6 @@ #include "AaptConfig.h" #include "ConfigDescription.h" #include "SdkConstants.h" -#include "TestHelper.h" using android::String8; @@ -127,4 +126,4 @@ TEST(AaptConfigTest, HdrQualifier) { config.colorMode & android::ResTable_config::MASK_HDR); EXPECT_EQ(SDK_O, config.sdkVersion); EXPECT_EQ(String8("lowdr-v26"), config.toString()); -}
\ No newline at end of file +} diff --git a/tools/aapt/tests/AaptGroupEntry_test.cpp b/tools/aapt/tests/AaptGroupEntry_test.cpp index 7348a08a022f..bf5ca59a81c8 100644 --- a/tools/aapt/tests/AaptGroupEntry_test.cpp +++ b/tools/aapt/tests/AaptGroupEntry_test.cpp @@ -19,7 +19,6 @@ #include "AaptAssets.h" #include "ResourceFilter.h" -#include "TestHelper.h" using android::String8; diff --git a/tools/aapt/tests/ResourceTable_test.cpp b/tools/aapt/tests/ResourceTable_test.cpp index f2c696b2f87e..0d550df16767 100644 --- a/tools/aapt/tests/ResourceTable_test.cpp +++ b/tools/aapt/tests/ResourceTable_test.cpp @@ -19,7 +19,6 @@ #include "ConfigDescription.h" #include "ResourceTable.h" -#include "TestHelper.h" using android::String16; diff --git a/tools/aapt/tests/TestHelper.h b/tools/aapt/tests/TestHelper.h deleted file mode 100644 index 79174832a54d..000000000000 --- a/tools/aapt/tests/TestHelper.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2014 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 __TEST_HELPER_H -#define __TEST_HELPER_H - -#include <utils/String8.h> - -namespace android { - -/** - * Stream operator for nicely printing String8's in gtest output. - */ -inline std::ostream& operator<<(std::ostream& stream, const String8& str) { - return stream << str.string(); -} - -} - -#endif diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index c1d05e47bc19..ade0dc4d9c42 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -47,6 +47,7 @@ cc_defaults { cflags: ["-D_DARWIN_UNLIMITED_STREAMS"], }, }, + header_libs: ["jni_headers"], static_libs: [ "libandroidfw", "libutils", diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index 234cbc4b37e0..931a14b1f650 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -449,6 +449,7 @@ bool ResourceParser::ParseResources(xml::XmlPullParser* parser) { ParsedResource parsed_resource; parsed_resource.config = config_; parsed_resource.source = source_.WithLine(parser->line_number()); + // NOLINTNEXTLINE(bugprone-use-after-move) move+reset comment parsed_resource.comment = std::move(comment); if (options_.visibility) { parsed_resource.visibility_level = options_.visibility.value(); @@ -979,6 +980,7 @@ bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource child_resource.name.type = *parsed_type; child_resource.name.entry = maybe_name.value().to_string(); child_resource.id = next_id; + // NOLINTNEXTLINE(bugprone-use-after-move) move+reset comment child_resource.comment = std::move(comment); child_resource.source = item_source; child_resource.visibility_level = Visibility::Level::kPublic; @@ -1698,6 +1700,7 @@ bool ResourceParser::ParseDeclareStyleable(xml::XmlPullParser* parser, ParsedResource child_resource; child_resource.name = child_ref.name.value(); child_resource.source = item_source; + // NOLINTNEXTLINE(bugprone-use-after-move) move+reset comment child_resource.comment = std::move(comment); if (options_.visibility) { child_resource.visibility_level = options_.visibility.value(); diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp index f9faed84f5f0..e8873bf2d81b 100644 --- a/tools/aapt2/SdkConstants.cpp +++ b/tools/aapt2/SdkConstants.cpp @@ -27,7 +27,7 @@ namespace aapt { static ApiVersion sDevelopmentSdkLevel = 10000; static const auto sDevelopmentSdkCodeNames = std::unordered_set<StringPiece>({ - "Q", "R" + "Q", "R", "S" }); static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = { diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 3a3fb2826b74..72cb41a1b172 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -1272,7 +1272,8 @@ class Linker { return false; } - ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout); + ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, + false /* strip_api_annotations */, &fout); fout.Flush(); if (fout.HadError()) { diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp index cec59e75831d..482d91aeb491 100644 --- a/tools/aapt2/java/AnnotationProcessor.cpp +++ b/tools/aapt2/java/AnnotationProcessor.cpp @@ -123,7 +123,7 @@ void AnnotationProcessor::AppendNewLine() { } } -void AnnotationProcessor::Print(Printer* printer) const { +void AnnotationProcessor::Print(Printer* printer, bool strip_api_annotations) const { if (has_comments_) { std::string result = comment_.str(); for (const StringPiece& line : util::Tokenize(result, '\n')) { @@ -137,6 +137,9 @@ void AnnotationProcessor::Print(Printer* printer) const { printer->Println("@Deprecated"); } + if (strip_api_annotations) { + return; + } for (const AnnotationRule& rule : sAnnotationRules) { const auto& it = annotation_parameter_map_.find(rule.bit_mask); if (it != annotation_parameter_map_.end()) { diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h index fdb58468d995..f217afb16f32 100644 --- a/tools/aapt2/java/AnnotationProcessor.h +++ b/tools/aapt2/java/AnnotationProcessor.h @@ -65,7 +65,7 @@ class AnnotationProcessor { void AppendNewLine(); // Writes the comments and annotations to the Printer. - void Print(text::Printer* printer) const; + void Print(text::Printer* printer, bool strip_api_annotations = false) const; private: std::stringstream comment_; diff --git a/tools/aapt2/java/AnnotationProcessor_test.cpp b/tools/aapt2/java/AnnotationProcessor_test.cpp index 7d0a4e9af632..6bc8902a6dcf 100644 --- a/tools/aapt2/java/AnnotationProcessor_test.cpp +++ b/tools/aapt2/java/AnnotationProcessor_test.cpp @@ -91,6 +91,21 @@ TEST(AnnotationProcessorTest, EmitsTestApiAnnotationAndRemovesFromComment) { EXPECT_THAT(annotations, HasSubstr("This is a test API")); } +TEST(AnnotationProcessorTest, NotEmitSystemApiAnnotation) { + AnnotationProcessor processor; + processor.AppendComment("@SystemApi This is a system API"); + + std::string annotations; + StringOutputStream out(&annotations); + Printer printer(&out); + processor.Print(&printer, true /* strip_api_annotations */); + out.Flush(); + + EXPECT_THAT(annotations, Not(HasSubstr("@android.annotation.SystemApi"))); + EXPECT_THAT(annotations, Not(HasSubstr("@SystemApi"))); + EXPECT_THAT(annotations, HasSubstr("This is a system API")); +} + TEST(AnnotationProcessor, ExtractsFirstSentence) { EXPECT_THAT(AnnotationProcessor::ExtractFirstSentence("This is the only sentence"), Eq("This is the only sentence")); diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp index f5f5b05491bb..3163497f0da6 100644 --- a/tools/aapt2/java/ClassDefinition.cpp +++ b/tools/aapt2/java/ClassDefinition.cpp @@ -23,15 +23,15 @@ using ::android::StringPiece; namespace aapt { -void ClassMember::Print(bool /*final*/, Printer* printer) const { - processor_.Print(printer); +void ClassMember::Print(bool /*final*/, Printer* printer, bool strip_api_annotations) const { + processor_.Print(printer, strip_api_annotations); } void MethodDefinition::AppendStatement(const StringPiece& statement) { statements_.push_back(statement.to_string()); } -void MethodDefinition::Print(bool final, Printer* printer) const { +void MethodDefinition::Print(bool final, Printer* printer, bool) const { printer->Print(signature_).Println(" {"); printer->Indent(); for (const auto& statement : statements_) { @@ -74,12 +74,12 @@ bool ClassDefinition::empty() const { return true; } -void ClassDefinition::Print(bool final, Printer* printer) const { +void ClassDefinition::Print(bool final, Printer* printer, bool strip_api_annotations) const { if (empty() && !create_if_empty_) { return; } - ClassMember::Print(final, printer); + ClassMember::Print(final, printer, strip_api_annotations); printer->Print("public "); if (qualifier_ == ClassQualifier::kStatic) { @@ -93,7 +93,7 @@ void ClassDefinition::Print(bool final, Printer* printer) const { // and takes precedence over a previous member with the same name. The overridden member is // set to nullptr. if (member != nullptr) { - member->Print(final, printer); + member->Print(final, printer, strip_api_annotations); printer->Println(); } } @@ -111,11 +111,11 @@ constexpr static const char* sWarningHeader = " */\n\n"; void ClassDefinition::WriteJavaFile(const ClassDefinition* def, const StringPiece& package, - bool final, io::OutputStream* out) { + bool final, bool strip_api_annotations, io::OutputStream* out) { Printer printer(out); printer.Print(sWarningHeader).Print("package ").Print(package).Println(";"); printer.Println(); - def->Print(final, &printer); + def->Print(final, &printer, strip_api_annotations); } } // namespace aapt diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h index fb11266f1761..1e4b6816075a 100644 --- a/tools/aapt2/java/ClassDefinition.h +++ b/tools/aapt2/java/ClassDefinition.h @@ -50,7 +50,7 @@ class ClassMember { // Writes the class member to the Printer. Subclasses should derive this method // to write their own data. Call this base method from the subclass to write out // this member's comments/annotations. - virtual void Print(bool final, text::Printer* printer) const; + virtual void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) const; private: AnnotationProcessor processor_; @@ -70,10 +70,11 @@ class PrimitiveMember : public ClassMember { return name_; } - void Print(bool final, text::Printer* printer) const override { + void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) + const override { using std::to_string; - ClassMember::Print(final, printer); + ClassMember::Print(final, printer, strip_api_annotations); printer->Print("public static "); if (final) { @@ -104,8 +105,9 @@ class PrimitiveMember<std::string> : public ClassMember { return name_; } - void Print(bool final, text::Printer* printer) const override { - ClassMember::Print(final, printer); + void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) + const override { + ClassMember::Print(final, printer, strip_api_annotations); printer->Print("public static "); if (final) { @@ -142,8 +144,9 @@ class PrimitiveArrayMember : public ClassMember { return name_; } - void Print(bool final, text::Printer* printer) const override { - ClassMember::Print(final, printer); + void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) + const override { + ClassMember::Print(final, printer, strip_api_annotations); printer->Print("public static final int[] ").Print(name_).Print("={"); printer->Indent(); @@ -195,7 +198,7 @@ class MethodDefinition : public ClassMember { return false; } - void Print(bool final, text::Printer* printer) const override; + void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) const override; private: DISALLOW_COPY_AND_ASSIGN(MethodDefinition); @@ -209,7 +212,7 @@ enum class ClassQualifier { kNone, kStatic }; class ClassDefinition : public ClassMember { public: static void WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package, - bool final, io::OutputStream* out); + bool final, bool strip_api_annotations, io::OutputStream* out); ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty) : name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {} @@ -227,7 +230,7 @@ class ClassDefinition : public ClassMember { return name_; } - void Print(bool final, text::Printer* printer) const override; + void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) const override; private: DISALLOW_COPY_AND_ASSIGN(ClassDefinition); diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index bb541fe2490b..dffad3b99c06 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -604,6 +604,8 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, rewrite_method->AppendStatement("final int packageIdBits = p << 24;"); } + const bool is_public = (options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic); + for (const auto& package : table_->packages) { for (const auto& type : package->types) { if (type->type == ResourceType::kAttrPrivate) { @@ -612,8 +614,7 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, } // Stay consistent with AAPT and generate an empty type class if the R class is public. - const bool force_creation_if_empty = - (options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic); + const bool force_creation_if_empty = is_public; std::unique_ptr<ClassDefinition> class_def; if (out != nullptr) { @@ -637,8 +638,7 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, } } - if (out != nullptr && type->type == ResourceType::kStyleable && - options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic) { + if (out != nullptr && type->type == ResourceType::kStyleable && is_public) { // When generating a public R class, we don't want Styleable to be part // of the API. It is only emitted for documentation purposes. class_def->GetCommentBuilder()->AppendComment("@doconly"); @@ -657,7 +657,7 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, if (out != nullptr) { AppendJavaDocAnnotations(options_.javadoc_annotations, r_class.GetCommentBuilder()); - ClassDefinition::WriteJavaFile(&r_class, out_package_name, options_.use_final, out); + ClassDefinition::WriteJavaFile(&r_class, out_package_name, options_.use_final, !is_public, out); } return true; } diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp index ab7f9a11d971..3858fc7f765e 100644 --- a/tools/aapt2/java/ManifestClassGenerator_test.cpp +++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp @@ -26,6 +26,7 @@ using ::testing::Not; namespace aapt { static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xml::XmlResource* res, + bool strip_api_annotations, std::string* out_str); TEST(ManifestClassGeneratorTest, NameIsProperlyGeneratedFromSymbol) { @@ -39,7 +40,8 @@ TEST(ManifestClassGeneratorTest, NameIsProperlyGeneratedFromSymbol) { </manifest>)"); std::string actual; - ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual)); + ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), + false /* strip_api_annotations */, &actual)); ASSERT_THAT(actual, HasSubstr("public static final class permission {")); ASSERT_THAT(actual, HasSubstr("public static final class permission_group {")); @@ -91,7 +93,8 @@ TEST(ManifestClassGeneratorTest, CommentsAndAnnotationsArePresent) { </manifest>)"); std::string actual; - ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual)); + ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), + false /* strip_api_annotations */, &actual)); const char* expected_access_internet = R"( /** * Required to access the internet. @@ -123,6 +126,55 @@ TEST(ManifestClassGeneratorTest, CommentsAndAnnotationsArePresent) { EXPECT_THAT(actual, HasSubstr(expected_test)); } +TEST(ManifestClassGeneratorTest, CommentsAndAnnotationsArePresentButNoApiAnnotations) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"( + <manifest xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- Required to access the internet. + Added in API 1. --> + <permission android:name="android.permission.ACCESS_INTERNET" /> + <!-- @deprecated This permission is for playing outside. --> + <permission android:name="android.permission.PLAY_OUTSIDE" /> + <!-- This is a private permission for system only! + @hide + @SystemApi --> + <permission android:name="android.permission.SECRET" /> + <!-- @TestApi This is a test only permission. --> + <permission android:name="android.permission.TEST_ONLY" /> + </manifest>)"); + + std::string actual; + ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), + true /* strip_api_annotations */, &actual)); + + const char* expected_access_internet = R"( /** + * Required to access the internet. + * Added in API 1. + */ + public static final String ACCESS_INTERNET="android.permission.ACCESS_INTERNET";)"; + EXPECT_THAT(actual, HasSubstr(expected_access_internet)); + + const char* expected_play_outside = R"( /** + * @deprecated This permission is for playing outside. + */ + @Deprecated + public static final String PLAY_OUTSIDE="android.permission.PLAY_OUTSIDE";)"; + EXPECT_THAT(actual, HasSubstr(expected_play_outside)); + + const char* expected_secret = R"( /** + * This is a private permission for system only! + * @hide + */ + public static final String SECRET="android.permission.SECRET";)"; + EXPECT_THAT(actual, HasSubstr(expected_secret)); + + const char* expected_test = R"( /** + * This is a test only permission. + */ + public static final String TEST_ONLY="android.permission.TEST_ONLY";)"; + EXPECT_THAT(actual, HasSubstr(expected_test)); +} + // This is bad but part of public API behaviour so we need to preserve it. TEST(ManifestClassGeneratorTest, LastSeenPermissionWithSameLeafNameTakesPrecedence) { std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); @@ -135,7 +187,8 @@ TEST(ManifestClassGeneratorTest, LastSeenPermissionWithSameLeafNameTakesPreceden </manifest>)"); std::string actual; - ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual)); + ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), + false /* strip_api_annotations */, &actual)); EXPECT_THAT(actual, HasSubstr("ACCESS_INTERNET=\"com.android.aapt.test.ACCESS_INTERNET\";")); EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"android.permission.ACCESS_INTERNET\";"))); EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"com.android.sample.ACCESS_INTERNET\";"))); @@ -149,11 +202,13 @@ TEST(ManifestClassGeneratorTest, NormalizePermissionNames) { </manifest>)"); std::string actual; - ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual)); + ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), + false /* strip_api_annotations */, &actual)); EXPECT_THAT(actual, HasSubstr("access_internet=\"android.permission.access-internet\";")); } static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xml::XmlResource* res, + bool strip_api_annotations, std::string* out_str) { std::unique_ptr<ClassDefinition> manifest_class = GenerateManifestClass(context->GetDiagnostics(), res); @@ -162,7 +217,7 @@ static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xm } StringOutputStream out(out_str); - manifest_class->WriteJavaFile(manifest_class.get(), "android", true, &out); + manifest_class->WriteJavaFile(manifest_class.get(), "android", true, strip_api_annotations, &out); out.Flush(); return ::testing::AssertionSuccess(); } diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp index 0db1807c75d9..d9a4caa34e0d 100644 --- a/tools/aapt2/java/ProguardRules.cpp +++ b/tools/aapt2/java/ProguardRules.cpp @@ -115,15 +115,10 @@ class LayoutVisitor : public BaseVisitor { void Visit(xml::Element* node) override { bool is_view = false; - bool is_fragment = false; if (node->namespace_uri.empty()) { if (node->name == "view") { is_view = true; - } else if (node->name == "fragment") { - is_fragment = true; } - } else if (node->namespace_uri == xml::kSchemaAndroid) { - is_fragment = node->name == "fragment"; } for (const auto& attr : node->attributes) { @@ -132,12 +127,12 @@ class LayoutVisitor : public BaseVisitor { if (is_view) { AddClass(node->line_number, attr.value, "android.content.Context, android.util.AttributeSet"); - } else if (is_fragment) { + } else { AddClass(node->line_number, attr.value, ""); } } } else if (attr.namespace_uri == xml::kSchemaAndroid && attr.name == "name") { - if (is_fragment && util::IsJavaClassName(attr.value)) { + if (util::IsJavaClassName(attr.value)) { AddClass(node->line_number, attr.value, ""); } } else if (attr.namespace_uri == xml::kSchemaAndroid && attr.name == "onClick") { diff --git a/tools/aapt2/java/ProguardRules_test.cpp b/tools/aapt2/java/ProguardRules_test.cpp index b6e76021ccc1..c7ae0b6a75cc 100644 --- a/tools/aapt2/java/ProguardRules_test.cpp +++ b/tools/aapt2/java/ProguardRules_test.cpp @@ -131,6 +131,61 @@ TEST(ProguardRulesTest, FragmentNameAndClassRulesAreEmitted) { EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(); }")); } +TEST(ProguardRulesTest, FragmentContainerViewNameRuleIsEmitted) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"( + <androidx.fragment.app.FragmentContainerView + xmlns:android="http://schemas.android.com/apk/res/android" + android:name="com.foo.Bar"/>)"); + layout->file.name = test::ParseNameOrDie("layout/foo"); + + proguard::KeepSet set; + ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set)); + + std::string actual = GetKeepSetString(set, /** minimal_rules */ false); + EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }")); + + actual = GetKeepSetString(set, /** minimal_rules */ true); + EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }")); +} + +TEST(ProguardRulesTest, FragmentContainerViewClassRuleIsEmitted) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + std::unique_ptr<xml::XmlResource> layout = + test::BuildXmlDom(R"(<androidx.fragment.app.FragmentContainerView class="com.foo.Bar"/>)"); + layout->file.name = test::ParseNameOrDie("layout/foo"); + + proguard::KeepSet set; + ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set)); + + std::string actual = GetKeepSetString(set, /** minimal_rules */ false); + EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }")); + + actual = GetKeepSetString(set, /** minimal_rules */ true); + EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }")); +} + +TEST(ProguardRulesTest, FragmentContainerViewNameAndClassRulesAreEmitted) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"( + <androidx.fragment.app.FragmentContainerView + xmlns:android="http://schemas.android.com/apk/res/android" + android:name="com.foo.Baz" + class="com.foo.Bar"/>)"); + layout->file.name = test::ParseNameOrDie("layout/foo"); + + proguard::KeepSet set; + ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set)); + + std::string actual = GetKeepSetString(set, /** minimal_rules */ false); + EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }")); + EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(...); }")); + + actual = GetKeepSetString(set, /** minimal_rules */ true); + EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }")); + EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(); }")); +} + TEST(ProguardRulesTest, NavigationFragmentNameAndClassRulesAreEmitted) { std::unique_ptr<IAaptContext> context = test::ContextBuilder() .SetCompilationPackage("com.base").Build(); diff --git a/tools/aapt2/util/BigBuffer_test.cpp b/tools/aapt2/util/BigBuffer_test.cpp index a7776e33ae74..64dcc1dad9a2 100644 --- a/tools/aapt2/util/BigBuffer_test.cpp +++ b/tools/aapt2/util/BigBuffer_test.cpp @@ -62,7 +62,7 @@ TEST(BigBufferTest, AppendAndMoveBlock) { *b1 = 44; buffer.AppendBuffer(std::move(buffer2)); - EXPECT_EQ(0u, buffer2.size()); + EXPECT_EQ(0u, buffer2.size()); // NOLINT EXPECT_EQ(buffer2.begin(), buffer2.end()); } diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp index 9a725fad8727..005eeb936612 100644 --- a/tools/aapt2/xml/XmlDom.cpp +++ b/tools/aapt2/xml/XmlDom.cpp @@ -305,6 +305,8 @@ std::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string* if (pending_element == nullptr) { pending_element = util::make_unique<Element>(); } + // pending_element is not nullptr + // NOLINTNEXTLINE(bugprone-use-after-move) pending_element->namespace_decls.push_back(std::move(decl)); break; } diff --git a/tools/bit/adb.cpp b/tools/bit/adb.cpp index fa7d3d4031d4..f521a63255e1 100644 --- a/tools/bit/adb.cpp +++ b/tools/bit/adb.cpp @@ -200,7 +200,7 @@ skip_bytes(int fd, ssize_t size, char* scratch, int scratchSize) static int skip_unknown_field(int fd, uint64_t tag, char* scratch, int scratchSize) { - bool done; + bool done = false; int err; uint64_t size; switch (tag & 0x7) { diff --git a/tools/dump-coverage/Android.bp b/tools/dump-coverage/Android.bp index 4519ce3636bf..94356ebac035 100644 --- a/tools/dump-coverage/Android.bp +++ b/tools/dump-coverage/Android.bp @@ -19,6 +19,7 @@ cc_library { name: "libdumpcoverage", srcs: ["dump_coverage.cc"], header_libs: [ + "jni_headers", "libopenjdkjvmti_headers", ], diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py index 6683e2abb0da..a4a315b7e371 100755 --- a/tools/fonts/fontchain_linter.py +++ b/tools/fonts/fontchain_linter.py @@ -286,7 +286,7 @@ def parse_fonts_xml(fonts_xml_path): if not fallback_for: if not name or name == 'sans-serif': - for _, fallback in _fallback_chains.iteritems(): + for _, fallback in _fallback_chains.items(): fallback.append(record) else: _fallback_chains[name].append(record) @@ -327,7 +327,7 @@ def check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji): assert sequence in all_emoji, ( 'Emoji font should not support %s.' % printable(sequence)) - for first, second in sorted(equivalent_emoji.items()): + for first, second in equivalent_emoji.items(): assert coverage[first] == coverage[second], ( '%s and %s should map to the same glyph.' % ( printable(first), @@ -352,7 +352,7 @@ def check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji): def check_emoji_defaults(default_emoji): missing_text_chars = _emoji_properties['Emoji'] - default_emoji - for name, fallback_chain in _fallback_chains.iteritems(): + for name, fallback_chain in _fallback_chains.items(): emoji_font_seen = False for record in fallback_chain: if 'Zsye' in record.scripts: @@ -369,7 +369,7 @@ def check_emoji_defaults(default_emoji): continue # Check default emoji-style characters - assert_font_supports_none_of_chars(record.font, sorted(default_emoji), name) + assert_font_supports_none_of_chars(record.font, default_emoji, name) # Mark default text-style characters appearing in fonts above the emoji # font as seen @@ -412,7 +412,7 @@ def parse_unicode_datafile(file_path, reverse=False): char_start, char_end = chars.split('..') char_start = int(char_start, 16) char_end = int(char_end, 16) - additions = xrange(char_start, char_end+1) + additions = range(char_start, char_end+1) else: # singe character additions = [int(chars, 16)] if reverse: @@ -478,7 +478,7 @@ def parse_ucd(ucd_path): # Unicode 12.0 adds Basic_Emoji in emoji-sequences.txt. We ignore them here since we are already # checking the emoji presentations with emoji-variation-sequences.txt. # Please refer to http://unicode.org/reports/tr51/#def_basic_emoji_set . - _emoji_sequences = {k: v for k, v in _emoji_sequences.iteritems() if not v == 'Basic_Emoji' } + _emoji_sequences = {k: v for k, v in _emoji_sequences.items() if not v == 'Basic_Emoji' } def remove_emoji_variation_exclude(source, items): @@ -551,7 +551,7 @@ def reverse_emoji(seq): rev = list(reversed(seq)) # if there are fitzpatrick modifiers in the sequence, keep them after # the emoji they modify - for i in xrange(1, len(rev)): + for i in range(1, len(rev)): if is_fitzpatrick_modifier(rev[i-1]): rev[i], rev[i-1] = rev[i-1], rev[i] return tuple(rev) @@ -620,7 +620,7 @@ def compute_expected_emoji(): def check_compact_only_fallback(): - for name, fallback_chain in _fallback_chains.iteritems(): + for name, fallback_chain in _fallback_chains.items(): for record in fallback_chain: if record.variant == 'compact': same_script_elegants = [x for x in fallback_chain @@ -650,7 +650,7 @@ def check_vertical_metrics(): def check_cjk_punctuation(): cjk_scripts = {'Hans', 'Hant', 'Jpan', 'Kore'} cjk_punctuation = range(0x3000, 0x301F + 1) - for name, fallback_chain in _fallback_chains.iteritems(): + for name, fallback_chain in _fallback_chains.items(): for record in fallback_chain: if record.scripts.intersection(cjk_scripts): # CJK font seen. Stop checking the rest of the fonts. diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py index 0b2077d9bba0..8a282e5f0821 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists.py +++ b/tools/hiddenapi/generate_hiddenapi_lists.py @@ -13,50 +13,70 @@ # 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. -""" -Generate API lists for non-SDK API enforcement. -""" +"""Generate API lists for non-SDK API enforcement.""" import argparse from collections import defaultdict +import functools import os -import sys import re -import functools +import sys # Names of flags recognized by the `hiddenapi` tool. -FLAG_WHITELIST = "whitelist" -FLAG_GREYLIST = "greylist" -FLAG_BLACKLIST = "blacklist" -FLAG_GREYLIST_MAX_O = "greylist-max-o" -FLAG_GREYLIST_MAX_P = "greylist-max-p" -FLAG_GREYLIST_MAX_Q = "greylist-max-q" -FLAG_CORE_PLATFORM_API = "core-platform-api" -FLAG_PUBLIC_API = "public-api" -FLAG_SYSTEM_API = "system-api" -FLAG_TEST_API = "test-api" +FLAG_SDK = 'sdk' +FLAG_UNSUPPORTED = 'unsupported' +FLAG_BLOCKED = 'blocked' +FLAG_MAX_TARGET_O = 'max-target-o' +FLAG_MAX_TARGET_P = 'max-target-p' +FLAG_MAX_TARGET_Q = 'max-target-q' +FLAG_MAX_TARGET_R = 'max-target-r' +FLAG_CORE_PLATFORM_API = 'core-platform-api' +FLAG_PUBLIC_API = 'public-api' +FLAG_SYSTEM_API = 'system-api' +FLAG_TEST_API = 'test-api' + +OLD_FLAG_SDK = "whitelist" +OLD_FLAG_UNSUPPORTED = "greylist" +OLD_FLAG_BLOCKED = "blacklist" +OLD_FLAG_MAX_TARGET_O = "greylist-max-o" +OLD_FLAG_MAX_TARGET_P = "greylist-max-p" +OLD_FLAG_MAX_TARGET_Q = "greylist-max-q" +OLD_FLAG_MAX_TARGET_R = "greylist-max-r" + +OLD_FLAGS_TO_NEW = { + OLD_FLAG_SDK: FLAG_SDK, + OLD_FLAG_UNSUPPORTED: FLAG_UNSUPPORTED, + OLD_FLAG_BLOCKED: FLAG_BLOCKED, + OLD_FLAG_MAX_TARGET_O: FLAG_MAX_TARGET_O, + OLD_FLAG_MAX_TARGET_P: FLAG_MAX_TARGET_P, + OLD_FLAG_MAX_TARGET_Q: FLAG_MAX_TARGET_Q, + OLD_FLAG_MAX_TARGET_R: FLAG_MAX_TARGET_R, +} + +NEW_FLAGS_TO_OLD = dict(zip(OLD_FLAGS_TO_NEW.values(), OLD_FLAGS_TO_NEW.keys())) # List of all known flags. FLAGS_API_LIST = [ - FLAG_WHITELIST, - FLAG_GREYLIST, - FLAG_BLACKLIST, - FLAG_GREYLIST_MAX_O, - FLAG_GREYLIST_MAX_P, - FLAG_GREYLIST_MAX_Q, + FLAG_SDK, + FLAG_UNSUPPORTED, + FLAG_BLOCKED, + FLAG_MAX_TARGET_O, + FLAG_MAX_TARGET_P, + FLAG_MAX_TARGET_Q, + FLAG_MAX_TARGET_R, ] ALL_FLAGS = FLAGS_API_LIST + [ FLAG_CORE_PLATFORM_API, FLAG_PUBLIC_API, FLAG_SYSTEM_API, FLAG_TEST_API, - ] +] FLAGS_API_LIST_SET = set(FLAGS_API_LIST) ALL_FLAGS_SET = set(ALL_FLAGS) # Suffix used in command line args to express that only known and # otherwise unassigned entries should be assign the given flag. -# For example, the P dark greylist is checked in as it was in P, +# For example, the max-target-P list is checked in as it was in P, # but signatures have changes since then. The flag instructs this # script to skip any entries which do not exist any more. FLAG_IGNORE_CONFLICTS_SUFFIX = "-ignore-conflicts" @@ -85,6 +105,7 @@ SERIALIZATION_REGEX = re.compile(r'.*->(' + '|'.join(SERIALIZATION_PATTERNS) + r HAS_NO_API_LIST_ASSIGNED = lambda api, flags: not FLAGS_API_LIST_SET.intersection(flags) IS_SERIALIZATION = lambda api, flags: SERIALIZATION_REGEX.match(api) + def get_args(): """Parses command line arguments. @@ -111,6 +132,7 @@ def get_args(): return parser.parse_args() + def read_lines(filename): """Reads entire file and return it as a list of lines. @@ -128,8 +150,9 @@ def read_lines(filename): lines = map(lambda line: line.strip(), lines) return set(lines) + def write_lines(filename, lines): - """Writes list of lines into a file, overwriting the file it it exists. + """Writes list of lines into a file, overwriting the file if it exists. Args: filename (string): Path to the file to be writting into. @@ -139,6 +162,7 @@ def write_lines(filename, lines): with open(filename, 'w') as f: f.writelines(lines) + def extract_package(signature): """Extracts the package from a signature. @@ -157,6 +181,7 @@ def extract_package(signature): package_name = full_class_name.rpartition("/")[0] return package_name.replace('/', '.') + class FlagsDict: def __init__(self): self._dict_keyset = set() @@ -180,6 +205,36 @@ class FlagsDict: "Please visit go/hiddenapi for more information.").format( source, "\n".join(flags_subset - ALL_FLAGS_SET)) + def convert_to_new_flag(self, flag): + """Converts old flag to a new variant. + + Flags that are considered old are replaced with new versions. + Otherwise, it is a no-op. + + Args: + flag: a string, representing SDK flag. + + Returns: + A string. Result of conversion. + + """ + return OLD_FLAGS_TO_NEW.get(flag, flag) + + def convert_to_old_flag(self, flag): + """Converts a new flag to a old variant. + + No-op if there is no suitable old flag. + Only used to support backwards compatibility. + + Args: + flag: a string, representing SDK flag. + + Returns: + A string. Result of conversion. + + """ + return NEW_FLAGS_TO_OLD.get(flag, flag) + def filter_apis(self, filter_fn): """Returns APIs which match a given predicate. @@ -210,10 +265,16 @@ class FlagsDict: def generate_csv(self): """Constructs CSV entries from a dictionary. + Old versions of flags are used to generate the file. + Returns: List of lines comprising a CSV file. See "parse_and_merge_csv" for format description. """ - return sorted(map(lambda api: ",".join([api] + sorted(self._dict[api])), self._dict)) + lines = [] + for api in self._dict: + flags = sorted([self.convert_to_old_flag(flag) for flag in self._dict[api]]) + lines.append(",".join([api] + flags)) + return sorted(lines) def parse_and_merge_csv(self, csv_lines, source = "<unknown>"): """Parses CSV entries and merges them into a given dictionary. @@ -235,17 +296,16 @@ class FlagsDict: self._dict_keyset.update([ csv[0] for csv in csv_values ]) # Check that all flags are known. - csv_flags = set(functools.reduce( - lambda x, y: set(x).union(y), - [ csv[1:] for csv in csv_values ], - [])) + csv_flags = set() + for csv in csv_values: + csv_flags.update([self.convert_to_new_flag(flag) for flag in csv[1:]]) self._check_flags_set(csv_flags, source) # Iterate over all CSV lines, find entry in dict and append flags to it. for csv in csv_values: - flags = csv[1:] + flags = [self.convert_to_new_flag(flag) for flag in csv[1:]] if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags): - flags.append(FLAG_WHITELIST) + flags.append(FLAG_SDK) self._dict[csv[0]].update(flags) def assign_flag(self, flag, apis, source="<unknown>"): @@ -269,6 +329,7 @@ class FlagsDict: for api in apis: self._dict[api].add(flag) + def main(argv): # Parse arguments. args = vars(get_args()) @@ -285,8 +346,8 @@ def main(argv): flags.parse_and_merge_csv(read_lines(filename), filename) # Combine inputs which do not require any particular order. - # (1) Assign serialization API to whitelist. - flags.assign_flag(FLAG_WHITELIST, flags.filter_apis(IS_SERIALIZATION)) + # (1) Assign serialization API to SDK. + flags.assign_flag(FLAG_SDK, flags.filter_apis(IS_SERIALIZATION)) # (2) Merge text files with a known flag into the dictionary. for flag in ALL_FLAGS: @@ -312,8 +373,8 @@ def main(argv): valid_entries = flags.filter_apis(should_add_signature_to_list) flags.assign_flag(flag, valid_entries) - # Assign all remaining entries to the blacklist. - flags.assign_flag(FLAG_BLACKLIST, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED)) + # Mark all remaining entries as blocked. + flags.assign_flag(FLAG_BLOCKED, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED)) # Write output. write_lines(args["output"], flags.generate_csv()) diff --git a/tools/hiddenapi/generate_hiddenapi_lists_test.py b/tools/hiddenapi/generate_hiddenapi_lists_test.py index 55c3a7d718db..321c400ef898 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists_test.py +++ b/tools/hiddenapi/generate_hiddenapi_lists_test.py @@ -23,7 +23,7 @@ class TestHiddenapiListGeneration(unittest.TestCase): # Initialize flags so that A and B are put on the whitelist and # C, D, E are left unassigned. Try filtering for the unassigned ones. flags = FlagsDict() - flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B,' + FLAG_WHITELIST, + flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B,' + FLAG_SDK, 'C', 'D', 'E']) filter_set = flags.filter_apis(lambda api, flags: not flags) self.assertTrue(isinstance(filter_set, set)) @@ -32,10 +32,10 @@ class TestHiddenapiListGeneration(unittest.TestCase): def test_get_valid_subset_of_unassigned_keys(self): # Create flags where only A is unassigned. flags = FlagsDict() - flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B', 'C']) - flags.assign_flag(FLAG_GREYLIST, set(['C'])) + flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B', 'C']) + flags.assign_flag(FLAG_UNSUPPORTED, set(['C'])) self.assertEqual(flags.generate_csv(), - [ 'A,' + FLAG_WHITELIST, 'B', 'C,' + FLAG_GREYLIST ]) + [ 'A,' + OLD_FLAG_SDK, 'B', 'C,' + OLD_FLAG_UNSUPPORTED ]) # Check three things: # (1) B is selected as valid unassigned @@ -50,20 +50,21 @@ class TestHiddenapiListGeneration(unittest.TestCase): # Test empty CSV entry. self.assertEqual(flags.generate_csv(), []) - # Test new additions. + # Test new additions. CSV generator produces values with old flags + # to be backwards compatible. flags.parse_and_merge_csv([ - 'A,' + FLAG_GREYLIST, - 'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O, - 'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST, - 'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API, - 'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API, + 'A,' + FLAG_UNSUPPORTED, + 'B,' + FLAG_BLOCKED + ',' + FLAG_MAX_TARGET_O, + 'C,' + FLAG_SDK + ',' + FLAG_SYSTEM_API, + 'D,' + FLAG_UNSUPPORTED + ',' + FLAG_TEST_API, + 'E,' + FLAG_BLOCKED + ',' + FLAG_TEST_API, ]) self.assertEqual(flags.generate_csv(), [ - 'A,' + FLAG_GREYLIST, - 'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O, - 'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST, - 'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API, - 'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API, + 'A,' + OLD_FLAG_UNSUPPORTED, + 'B,' + OLD_FLAG_BLOCKED + "," + OLD_FLAG_MAX_TARGET_O, + 'C,' + FLAG_SYSTEM_API + ',' + OLD_FLAG_SDK, + 'D,' + OLD_FLAG_UNSUPPORTED + ',' + FLAG_TEST_API, + 'E,' + OLD_FLAG_BLOCKED + ',' + FLAG_TEST_API, ]) # Test unknown flag. @@ -72,16 +73,16 @@ class TestHiddenapiListGeneration(unittest.TestCase): def test_assign_flag(self): flags = FlagsDict() - flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B']) + flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B']) # Test new additions. - flags.assign_flag(FLAG_GREYLIST, set([ 'A', 'B' ])) + flags.assign_flag(FLAG_UNSUPPORTED, set([ 'A', 'B' ])) self.assertEqual(flags.generate_csv(), - [ 'A,' + FLAG_GREYLIST + "," + FLAG_WHITELIST, 'B,' + FLAG_GREYLIST ]) + [ 'A,' + OLD_FLAG_UNSUPPORTED + "," + OLD_FLAG_SDK, 'B,' + OLD_FLAG_UNSUPPORTED ]) # Test invalid API signature. with self.assertRaises(AssertionError): - flags.assign_flag(FLAG_WHITELIST, set([ 'C' ])) + flags.assign_flag(FLAG_SDK, set([ 'C' ])) # Test invalid flag. with self.assertRaises(AssertionError): diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp index 786223a430ae..dd266ffe0f16 100644 --- a/tools/incident_section_gen/main.cpp +++ b/tools/incident_section_gen/main.cpp @@ -368,10 +368,13 @@ static bool generatePrivacyFlags(const Descriptor* descriptor, const Destination // Don't generate a variable twice if (!hasDefaultFlags[i]) variableNames[fieldName] = false; } + // hasDefaultFlags[i] has been initialized in the above for-loop, + // but clang-tidy analyzer still report uninitized values. + // So we use NOLINT to suppress those false positives. bool allDefaults = true; for (size_t i=0; i<fieldsInOrder.size(); i++) { - allDefaults &= hasDefaultFlags[i]; + allDefaults &= hasDefaultFlags[i]; // NOLINT(clang-analyzer-core.uninitialized.Assign) } parents->erase(messageName); // erase the message type name when exit the message. @@ -384,7 +387,7 @@ static bool generatePrivacyFlags(const Descriptor* descriptor, const Destination printf("Privacy* %s[] = {\n", messageName.c_str()); for (size_t i=0; i<fieldsInOrder.size(); i++) { const FieldDescriptor* field = fieldsInOrder[i]; - if (hasDefaultFlags[i]) continue; + if (hasDefaultFlags[i]) continue; // NOLINT(clang-analyzer-core.uninitialized.Branch) printf(" &%s,\n", getFieldName(field).c_str()); policyCount++; } |