Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] Improve AAPT error granularity (#3577)
Browse files Browse the repository at this point in the history
Context: https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems/edit/735263
Context: https://android.googlesource.com/platform/frameworks/base/+/563abce4ed0a0d9f08f8839a8f15b548b3dcd4d1/tools/aapt
Context: https://gist.github.com/grendello/72c1ce5f6e8cdd3aefd393b983576d9a

Errors and warning *codes* for errors and warnings reported
*within Visual Studio* from developers participating in the
[Visual Studio Customer Experience Improvement Program][0] are
reported "telemetry" events, but *only* the error and warning codes
are reported.  The warning and error message contents are not sent.

Unfortunately all `aapt`-related errors are reported as APT0000,
which reduces the utility of telemetry, making it more difficult to
better understand where our build system could be improved.

@grendello created a `grep` pipeline for the `aapt` sources to try to
extract plausible error messages that we can compare against.  The
exact pipeline has been lost, but this is an in-progress pipeline
for finding error messages from the `aapt2` sources:

	rgrep -Pzoh '(?s)(->|\.)Error.*?;\n' * | \
	  tr -d '\n' | tr ';' '\n'| \
	  sed -e 's/^[ \t]*//g' -e 's/^.*Error([ \t]*DiagMessage[ \t]*(.*)[ \t]*<<//g' -e 's/^.*Error(.*)//g;' -e 's/^;$//g' | \
	  sort | uniq

Improve the `<Aapt/>` task to check against this list of "known"
error strings and associate them with unique `APTxxxx` codes.
This will allow for more meaningful documentation to be written
in the future, and will allow our telemetry to be more meaningful
and permit improved focusing of future efforts.

[0]: https://docs.microsoft.com/en-us/visualstudio/ide/visual-studio-experience-improvement-program?view=vs-2019
  • Loading branch information
jpobst authored and jonpryor committed Sep 6, 2019
1 parent 87f9f9a commit 2d400aa
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 9 deletions.
172 changes: 168 additions & 4 deletions src/Xamarin.Android.Build.Tasks/Tasks/Aapt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ protected void LogEventsFromTextOutput (string singleLine, MessageImportance mes
return;
}
if (level.Contains ("warning")) {
LogCodedWarning ("APT0000", singleLine);
LogCodedWarning (GetErrorCode (singleLine), singleLine);
return;
}

Expand All @@ -430,16 +430,180 @@ protected void LogEventsFromTextOutput (string singleLine, MessageImportance mes
message = message.Substring ("error: ".Length);

if (level.Contains ("error") || (line != 0 && !string.IsNullOrEmpty (file))) {
LogCodedError ("APT0000", message, file, line);
LogCodedError (GetErrorCode (message), message, file, line);
return;
}
}

if (!apptResult) {
LogCodedError ("APT0000", string.Format ("{0} \"{1}\".", singleLine.Trim (), singleLine.Substring (singleLine.LastIndexOfAny (new char [] { '\\', '/' }) + 1)), ToolName);
var message = string.Format ("{0} \"{1}\".", singleLine.Trim (), singleLine.Substring (singleLine.LastIndexOfAny (new char [] { '\\', '/' }) + 1));
LogCodedError (GetErrorCode (message), message, ToolName);
} else {
LogCodedWarning ("APT0000", singleLine);
LogCodedWarning (GetErrorCode (singleLine), singleLine);
}
}

static string GetErrorCode (string message)
{
foreach (var tuple in error_codes)
if (message.IndexOf (tuple.Item2, StringComparison.OrdinalIgnoreCase) >= 0)
return tuple.Item1;

return "APT1000";
}

static readonly List<Tuple<string, string>> error_codes = new List<Tuple<string, string>> () {
Tuple.Create ("APT1001", "can't use '-u' with add"),
Tuple.Create ("APT1002", "dump failed because assets could not be loaded"),
Tuple.Create ("APT1003", "dump failed because no AndroidManifest.xml found"),
Tuple.Create ("APT1004", "dump failed because the resource table is invalid/corrupt"),
Tuple.Create ("APT1005", "during crunch - archive is toast"),
Tuple.Create ("APT1006", "failed to get platform version code"),
Tuple.Create ("APT1007", "failed to get platform version name"),
Tuple.Create ("APT1008", "failed to get XML element name (bad string pool)"),
Tuple.Create ("APT1009", "failed to write library table"),
Tuple.Create ("APT1010", "getting resolved resource attribute"),
Tuple.Create ("APT1011", "Key string data is corrupt"),
Tuple.Create ("APT1012", "list -a failed because assets could not be loaded"),
Tuple.Create ("APT1013", "manifest does not start with <manifest> tag"),
Tuple.Create ("APT1014", "missing 'android:name' for permission"),
Tuple.Create ("APT1015", "missing 'android:name' for uses-permission"),
Tuple.Create ("APT1016", "missing 'android:name' for uses-permission-sdk-23"),
Tuple.Create ("APT1017", "Missing entries, quit"),
Tuple.Create ("APT1018", "must specify zip file name"),
Tuple.Create ("APT1019", "No AndroidManifest.xml file found"),
Tuple.Create ("APT1020", "No argument supplied for '-A' option"),
Tuple.Create ("APT1021", "No argument supplied for '-c' option"),
Tuple.Create ("APT1022", "No argument supplied for '--custom-package' option"),
Tuple.Create ("APT1023", "No argument supplied for '-D' option"),
Tuple.Create ("APT1024", "No argument supplied for '-e' option"),
Tuple.Create ("APT1025", "No argument supplied for '--extra-packages' option"),
Tuple.Create ("APT1026", "No argument supplied for '--feature-after' option"),
Tuple.Create ("APT1027", "No argument supplied for '--feature-of' option"),
Tuple.Create ("APT1028", "No argument supplied for '-F' option"),
Tuple.Create ("APT1029", "No argument supplied for '-g' option"),
Tuple.Create ("APT1030", "No argument supplied for '--ignore-assets' option"),
Tuple.Create ("APT1031", "No argument supplied for '-I' option"),
Tuple.Create ("APT1032", "No argument supplied for '-j' option"),
Tuple.Create ("APT1033", "No argument supplied for '--max-res-version' option"),
Tuple.Create ("APT1034", "No argument supplied for '--max-sdk-version' option"),
Tuple.Create ("APT1035", "No argument supplied for '--min-sdk-version' option"),
Tuple.Create ("APT1036", "No argument supplied for '-M' option"),
Tuple.Create ("APT1037", "No argument supplied for '-o' option"),
Tuple.Create ("APT1038", "No argument supplied for '-output-text-symbols' option"),
Tuple.Create ("APT1039", "No argument supplied for '-P' option"),
Tuple.Create ("APT1040", "No argument supplied for '--preferred-density' option"),
Tuple.Create ("APT1041", "No argument supplied for '--private-symbols' option"),
Tuple.Create ("APT1042", "No argument supplied for '--product' option"),
Tuple.Create ("APT1043", "No argument supplied for '--rename-instrumentation-target-package' option"),
Tuple.Create ("APT1044", "No argument supplied for '--rename-manifest-package' option"),
Tuple.Create ("APT1045", "No argument supplied for '-S' option"),
Tuple.Create ("APT1046", "No argument supplied for '--split' option"),
Tuple.Create ("APT1047", "No argument supplied for '--target-sdk-version' option"),
Tuple.Create ("APT1048", "No argument supplied for '--version-code' option"),
Tuple.Create ("APT1049", "No argument supplied for '--version-name' option"),
Tuple.Create ("APT1050", "no dump file specified"),
Tuple.Create ("APT1051", "no dump option specified"),
Tuple.Create ("APT1052", "no dump xmltree resource file specified"),
Tuple.Create ("APT1053", "no input files"),
Tuple.Create ("APT1054", "no <manifest> tag found in platform AndroidManifest.xml"),
Tuple.Create ("APT1055", "out of memory creating package chunk for ResTable_header"),
Tuple.Create ("APT1056", "out of memory creating ResTable_entry"),
Tuple.Create ("APT1057", "out of memory creating ResTable_header"),
Tuple.Create ("APT1058", "out of memory creating ResTable_package"),
Tuple.Create ("APT1059", "out of memory creating ResTable_type"),
Tuple.Create ("APT1060", "out of memory creating ResTable_typeSpec"),
Tuple.Create ("APT1061", "out of memory creating Res_value"),
Tuple.Create ("APT1062", "Out of memory for string pool"),
Tuple.Create ("APT1063", "Out of memory padding string pool"),
Tuple.Create ("APT1064", "parsing XML"),
Tuple.Create ("APT1065", "Platform AndroidManifest.xml is corrupt"),
Tuple.Create ("APT1066", "Platform AndroidManifest.xml not found"),
Tuple.Create ("APT1067", "print resolved resource attribute"),
Tuple.Create ("APT1068", "retrieving parent for item:"),
Tuple.Create ("APT1069", "specify zip file name (only)"),
Tuple.Create ("APT1070", "Type string data is corrupt"),
Tuple.Create ("APT1071", "Unable to parse generated resources, aborting"),
Tuple.Create ("APT1072", "Invalid BCP 47 tag in directory name"), // ERROR: Invalid BCP 47 tag in directory name: %s
Tuple.Create ("APT1073", "parsing preferred density"), // Error parsing preferred density: %s
Tuple.Create ("APT1074", "Asset package include"), // ERROR: Asset package include '%s' not found
Tuple.Create ("APT1075", "base feature package"), // ERROR: base feature package '%s' not found
Tuple.Create ("APT1076", "Split configuration"), // ERROR: Split configuration '%s' is already defined in another split
Tuple.Create ("APT1077", "failed opening/creating"), // ERROR: failed opening/creating '%s' as Zip file
Tuple.Create ("APT1078", "as Zip file for writing"), // ERROR: unable to open '%s' as Zip file for writing
Tuple.Create ("APT1079", "as Zip file"), // ERROR: failed opening '%s' as Zip file
Tuple.Create ("APT1080", "included asset path"), // ERROR: included asset path %s could not be loaded
Tuple.Create ("APT1081", "getting 'android:name' attribute"),
Tuple.Create ("APT1082", "getting 'android:name'"),
Tuple.Create ("APT1083", "getting 'android:versionCode' attribute"),
Tuple.Create ("APT1084", "getting 'android:versionName' attribute"),
Tuple.Create ("APT1085", "getting 'android:compileSdkVersion' attribute"),
Tuple.Create ("APT1086", "getting 'android:installLocation' attribute"),
Tuple.Create ("APT1087", "getting 'android:icon' attribute"),
Tuple.Create ("APT1088", "getting 'android:testOnly' attribute"),
Tuple.Create ("APT1089", "getting 'android:banner' attribute"),
Tuple.Create ("APT1090", "getting 'android:isGame' attribute"),
Tuple.Create ("APT1091", "getting 'android:debuggable' attribute"),
Tuple.Create ("APT1092", "getting 'android:minSdkVersion' attribute"),
Tuple.Create ("APT1093", "getting 'android:targetSdkVersion' attribute"),
Tuple.Create ("APT1094", "getting 'android:label' attribute"),
Tuple.Create ("APT1095", "getting compatible screens"),
Tuple.Create ("APT1096", "getting 'android:name' attribute for uses-library"),
Tuple.Create ("APT1097", "getting 'android:name' attribute for receiver"),
Tuple.Create ("APT1098", "getting 'android:permission' attribute for receiver"),
Tuple.Create ("APT1099", "getting 'android:name' attribute for service"),
Tuple.Create ("APT1100", "getting 'android:name' attribute for meta-data tag in service"),
Tuple.Create ("APT1101", "getting 'android:name' attribute for meta-data"),
Tuple.Create ("APT1102", "getting 'android:permission' attribute for service"),
Tuple.Create ("APT1103", "getting 'android:permission' attribute for provider"),
Tuple.Create ("APT1104", "getting 'android:exported' attribute for provider"),
Tuple.Create ("APT1105", "getting 'android:grantUriPermissions' attribute for provider"),
Tuple.Create ("APT1106", "getting 'android:value' or 'android:resource' attribute for meta-data"),
Tuple.Create ("APT1107", "getting 'android:resource' attribute for meta-data tag in service"),
Tuple.Create ("APT1108", "getting AID category for service"),
Tuple.Create ("APT1109", "getting 'name' attribute"),
Tuple.Create ("APT1110", "unknown dump option"),
Tuple.Create ("APT1111", "failed opening Zip archive"),
Tuple.Create ("APT1112", "exists but is not regular file"), // ERROR: output file '%s' exists but is not regular file
Tuple.Create ("APT1113", "failed to parse split configuration"),
Tuple.Create ("APT1114", "packaging of"), // ERROR: packaging of '%s' failed
Tuple.Create ("APT1115", "9-patch image"), // ERROR: 9-patch image %s malformed
Tuple.Create ("APT1116", "Failure processing PNG image"),
Tuple.Create ("APT1117", "Unknown command"),
Tuple.Create ("APT1118", "exists (use '-f' to force overwrite)"),
Tuple.Create ("APT1119", "exists and is not a regular file"),
Tuple.Create ("APT1120", "unable to process assets while packaging"),
Tuple.Create ("APT1121", "unable to process jar files while packaging"),
Tuple.Create ("APT1122", "Unknown option"),
Tuple.Create ("APT1123", "Unknown flag"),
Tuple.Create ("APT1124", "Zip flush failed, archive may be hosed"),
Tuple.Create ("APT1125", "exists twice (check for with"), // ERROR: '%s' exists twice (check for with & w/o '.gz'?)
Tuple.Create ("APT1126", "unable to uncompress entry"),
Tuple.Create ("APT1127", "as a zip file"), // ERROR: unable to open '%s' as a zip file: %d
Tuple.Create ("APT1128", "unable to process"), // ERROR: unable to process '%s'
Tuple.Create ("APT1129", "malformed resource filename"),
Tuple.Create ("APT1130", "AndroidManifest.xml already defines"), // Error: AndroidManifest.xml already defines %s (in %s); cannot insert new value %s
Tuple.Create ("APT1131", "In <declare-styleable>"), // ERROR: In <declare-styleable> %s, unable to find attribute %s
Tuple.Create ("APT1132", "Feature package"), // ERROR: Feature package '%s' not found
Tuple.Create ("APT1133", "declaring public resource"), // Error declaring public resource %s/%s for included package %s
Tuple.Create ("APT1134", "with value"), // Error: %s (at '%s' with value '%s')
Tuple.Create ("APT1135", "is not a single item or a bag"), // Error: entry %s is not a single item or a bag
Tuple.Create ("APT1136", "adding span for style tag"),
Tuple.Create ("APT1137", "parsing XML"),
Tuple.Create ("APT1138", "access denied"), // ERROR: '%s' access denied
Tuple.Create ("APT1139", "included asset path"), // ERROR: included asset path %s could not be loaded
Tuple.Create ("APT1140", "is corrupt"), // ERROR: Resource %s is corrupt
Tuple.Create ("APT1141", "dump failed because resource"), // ERROR: dump failed because resource %s [not] found
Tuple.Create ("APT1142", "not found"), // ERROR: '%s' not found
Tuple.Create ("APT1043", "asset directory"), // ERROR: asset directory '%s' does not exist
Tuple.Create ("APT1044", "input directory"), // ERROR: input directory '%s' does not exist
Tuple.Create ("APT1045", "resource directory"), // ERROR: resource directory '%s' does not exist
Tuple.Create ("APT1046", "is not a directory"), // ERROR: '%s' is not a directory
Tuple.Create ("APT1047", "opening zip file"), // error opening zip file %s
Tuple.Create ("APT1143", "AndroidManifest.xml is corrupt"),
Tuple.Create ("APT1144", "Invalid file name: must contain only"),
Tuple.Create ("APT1145", "has no default translation"),
Tuple.Create ("APT1146", "max res"),
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public void ReportAaptWarningsForBlankLevel ([Values (false, true)] bool useAapt
using (var b = CreateApkBuilder ($"temp/{TestName}")) {
b.ThrowOnBuildFailure = false;
Assert.IsFalse (b.Build (proj), "Build should have failed.");
StringAssertEx.Contains ("APT0000", b.LastBuildOutput, "An error message with a blank \"level\", should be reported as an error!");
StringAssertEx.Contains (useAapt2 ? "APT0000" : "APT1144", b.LastBuildOutput, "An error message with a blank \"level\", should be reported as an error!");
Assert.IsTrue (b.Clean (proj), "Clean should have succeeded.");
}
}
Expand Down Expand Up @@ -1281,8 +1281,8 @@ public void CheckMaxResWarningIsEmittedAsAWarning([Values (false, true)] bool us
if (useAapt2) {
StringAssertEx.DoesNotContain ("APT0000", builder.LastBuildOutput, "Build output should not contain an APT0000 warning");
} else {
var expected = builder.RunningMSBuild ? "warning APT0000: max res 26, skipping values-v27" : "warning APT0000: warning : max res 26, skipping values-v27";
StringAssertEx.Contains (expected, builder.LastBuildOutput, "Build output should contain an APT0000 warning about 'max res 26, skipping values-v27'");
var expected = builder.RunningMSBuild ? "warning APT1146: max res 26, skipping values-v27" : "warning APT1146: warning : max res 26, skipping values-v27";
StringAssertEx.Contains (expected, builder.LastBuildOutput, "Build output should contain an APT1146 warning about 'max res 26, skipping values-v27'");
}
}
}
Expand All @@ -1309,7 +1309,7 @@ public void CheckDefaultTranslationWarnings ()
});
using (var builder = CreateApkBuilder (path, false, false)) {
Assert.IsTrue (builder.Build (proj), "Build should have succeeded.");
StringAssertEx.Contains ($"warning APT0000: warning: string '{name}' has no default translation.", builder.LastBuildOutput, "Build output should contain an APT0000 warning about 'no default translation'");
StringAssertEx.Contains ($"warning APT1145: warning: string '{name}' has no default translation.", builder.LastBuildOutput, "Build output should contain an APT0000 warning about 'no default translation'");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public void Bug12935 ([Values (true, false)] bool useAapt2)
proj.TargetFrameworkVersion = "v4.0.3";
proj.AndroidManifest = string.Format (TargetSdkManifest, "15");
Assert.IsFalse (builder.Build (proj), "Build for TargetFrameworkVersion 15 should have failed");
StringAssertEx.Contains ("APT0000: ", builder.LastBuildOutput);
StringAssertEx.Contains (useAapt2 ? "APT0000: " : "APT1134: ", builder.LastBuildOutput);
StringAssertEx.Contains ("1 Error(s)", builder.LastBuildOutput);
}
}
Expand Down

0 comments on commit 2d400aa

Please sign in to comment.