Skip to content

Commit 2e95c8e

Browse files
committed
Begin error documentation.
1 parent 49defda commit 2e95c8e

File tree

9 files changed

+187
-109
lines changed

9 files changed

+187
-109
lines changed

Documentation/guides/ResolvingJavaDependencies.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@ This can be done by adding additional `<AndroidLibrary>` items to the project:
6464

6565
```xml
6666
<ItemGroup>
67-
<AndroidLibrary JavaArtifact="my.library:dependency-library" JavaVersion="1.0.0" />
67+
<AndroidLibrary Include="mydependency.jar" JavaArtifact="my.library:dependency-library" JavaVersion="1.0.0" />
6868
</ItemGroup>
6969
```
7070

7171
To include the Java library but not produce C# bindings for it, mark it with `Bind="false"`:
7272

7373
```xml
7474
<ItemGroup>
75-
<AndroidLibrary JavaArtifact="my.library:dependency-library" JavaVersion="1.0.0" Bind="false" />
75+
<AndroidLibrary Include="mydependency.jar" JavaArtifact="my.library:dependency-library" JavaVersion="1.0.0" Bind="false" />
7676
</ItemGroup>
7777
```
7878

external/Java.Interop

src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs

Lines changed: 81 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Xamarin.Android.Build.Tasks/Properties/Resources.resx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,4 +1008,54 @@ To use a custom JDK path for a command line build, set the 'JavaSdkDirectory' MS
10081008
<value>The Android Support libraries are not supported in .NET 9 and later, please migrate to AndroidX. See https://aka.ms/xamarin/androidx for more details.</value>
10091009
<comment>The following are literal names and should not be translated: Android Support, AndroidX, .NET.</comment>
10101010
</data>
1011+
<data name="XA4240" xml:space="preserve">
1012+
<value>Could not verify Java dependencies for artifact '{0}' due to missing POM file(s). See other error(s) for details.</value>
1013+
<comment>The following are literal names and should not be translated: Java, POM.
1014+
{0} - Maven artifact id</comment>
1015+
</data>
1016+
<data name="XA4241" xml:space="preserve">
1017+
<value>Java dependency '{0}' is not satisfied.</value>
1018+
<comment>The following are literal names and should not be translated: Java.
1019+
{0} - Maven dependency id</comment>
1020+
</data>
1021+
<data name="XA4242" xml:space="preserve">
1022+
<value>Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency.</value>
1023+
<comment>The following are literal names and should not be translated: Java, Microsoft, NuGet.
1024+
{0} - Maven dependency id
1025+
{1} - NuGet package id</comment>
1026+
</data>
1027+
<data name="XA4243" xml:space="preserve">
1028+
<value>Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'.</value>
1029+
<comment>{0}, {1} - MSBuild XML attribute
1030+
{2} - MSBuild XML element name
1031+
{3} - MSBuild ItemSpec value</comment>
1032+
</data>
1033+
<data name="XA4244" xml:space="preserve">
1034+
<value>Attribute '{0}' cannot be empty for '{1}' item '{2}'.</value>
1035+
<comment>{0} - MSBuild XML attribute
1036+
{1} - MSBuild XML element name
1037+
{2} - MSBuild ItemSpec value</comment>
1038+
</data>
1039+
<data name="XA4245" xml:space="preserve">
1040+
<value>Specified POM file '{0}' does not exist.</value>
1041+
<comment>The following are literal names and should not be translated: POM.
1042+
{0} - File path to POM file</comment>
1043+
</data>
1044+
<data name="XA4246" xml:space="preserve">
1045+
<value>Could not parse POM file '{0}': '{1}'.</value>
1046+
<comment>The following are literal names and should not be translated: POM.
1047+
{0} - File path to POM file
1048+
{1} - Exception message</comment>
1049+
</data>
1050+
<data name="XA4247" xml:space="preserve">
1051+
<value>Could not resolve POM file for artifact '{0}'.</value>
1052+
<comment>The following are literal names and should not be translated: POM.
1053+
{0} - Java artifact id</comment>
1054+
</data>
1055+
<data name="XA4248" xml:space="preserve">
1056+
<value>Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this &lt;PackageReference&gt; was added.</value>
1057+
<comment>The following are literal names and should not be translated: NuGet, PackageReference.
1058+
{0} - NuGet package id
1059+
{1} - NuGet package version</comment>
1060+
</data>
10111061
</root>

src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs

Lines changed: 31 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@ public override bool RunTask ()
6666
if (pom_resolver.RegisterFromAndroidLibrary (pom) is Artifact art)
6767
poms_to_verify.Add (art);
6868

69-
//foreach (var pom in AndroidLibraries.Select (al => al.GetMetadata ("Manifest")))
70-
// if (pom.HasValue () && pom_resolver.Register (pom) is Artifact art)
71-
// poms_to_verify.Add (art);
72-
7369
foreach (var pom in AdditionalManifests ?? [])
7470
pom_resolver.RegisterFromAndroidAdditionalJavaManifest (pom);
7571

@@ -94,7 +90,7 @@ public override bool RunTask ()
9490
foreach (var dependency in resolved_pom.Dependencies.Where (d => (d.IsRuntimeDependency () || d.IsCompileDependency ()) && !d.IsOptional ()))
9591
resolver.EnsureDependencySatisfied (dependency, ms_packages);
9692
} else {
97-
Log.LogError ("Could not verify Java dependencies for artifact '{0}' due to missing POM file(s). See other error(s) for details.", pom);
93+
Log.LogCodedError ("XA4240", Properties.Resources.XA4240, pom);
9894
}
9995
}
10096

@@ -117,7 +113,7 @@ static bool TryResolveProject (Artifact artifact, IPomResolver resolver, [NotNul
117113

118114
class DependencyResolver
119115
{
120-
List<Artifact> artifacts = new List<Artifact> ();
116+
readonly List<Artifact> artifacts = new List<Artifact> ();
121117

122118
readonly NuGetPackageVersionFinder? finder;
123119
readonly TaskLoggingHelper log;
@@ -133,30 +129,20 @@ public DependencyResolver (string? lockFile, TaskLoggingHelper log)
133129
public bool EnsureDependencySatisfied (ResolvedDependency dependency, MicrosoftNuGetPackageFinder packages)
134130
{
135131
if (!dependency.Version.HasValue ())
136-
log.LogWarning ("Could not determine required version of Java dependency '{0}:{1}'. Validation of this dependency will not take version into account.", dependency.GroupId, dependency.ArtifactId);
132+
log.LogMessage ("Could not determine required version of Java dependency '{0}:{1}'. Validation of this dependency will not take version into account.", dependency.GroupId, dependency.ArtifactId);
137133

138134
var satisfied = TrySatisfyDependency (dependency);
139135

140136
if (satisfied)
141137
return true;
142138

143139
var suggestion = packages.GetNuGetPackage ($"{dependency.GroupId}:{dependency.ArtifactId}");
140+
var artifact_spec = dependency.ToArtifactString (dependency.Version.HasValue ());
144141

145-
// Message if we couldn't determine the required version
146-
if (!dependency.Version.HasValue ()) {
147-
if (suggestion is string nuget)
148-
log.LogError ("Java dependency '{0}:{1}' is not satisfied. Microsoft maintains the NuGet package '{2}' that could fulfill this dependency.", dependency.GroupId, dependency.ArtifactId, nuget);
149-
else
150-
log.LogError ("Java dependency '{0}:{1}' is not satisfied.", dependency.GroupId, dependency.ArtifactId);
151-
152-
return false;
153-
}
154-
155-
// Message if we could determine the required version
156-
if (suggestion is string nuget2)
157-
log.LogError ("Java dependency '{0}:{1}' version '{2}' is not satisfied. Microsoft maintains the NuGet package '{3}' that could fulfill this dependency.", dependency.GroupId, dependency.ArtifactId, dependency.Version, nuget2);
142+
if (suggestion is string nuget)
143+
log.LogCodedError ("XA4242", Properties.Resources.XA4242, artifact_spec, nuget);
158144
else
159-
log.LogError ("Java dependency '{0}:{1}' version '{2}' is not satisfied.", dependency.GroupId, dependency.ArtifactId, dependency.Version);
145+
log.LogCodedError ("XA4242", Properties.Resources.XA4241, artifact_spec);
160146

161147
return false;
162148
}
@@ -183,7 +169,13 @@ public void AddPackageReferences (ITaskItem []? tasks)
183169
foreach (var task in tasks.OrEmpty ()) {
184170

185171
// See if JavaArtifact/JavaVersion overrides were used
186-
if (TryParseJavaArtifactAndVersion ("PackageReference", task))
172+
if (task.TryParseJavaArtifactAndJavaVersion ("PackageReference", log, out var explicit_artifact, out var attributes_specified)) {
173+
artifacts.Add (explicit_artifact);
174+
continue;
175+
}
176+
177+
// If user tried to specify JavaArtifact or JavaVersion, but did it incorrectly, we do not perform any fallback
178+
if (attributes_specified)
187179
continue;
188180

189181
// Try parsing the NuGet metadata for Java version information instead
@@ -204,7 +196,13 @@ public void AddProjectReferences (ITaskItem []? tasks)
204196
{
205197
foreach (var task in tasks.OrEmpty ()) {
206198
// See if JavaArtifact/JavaVersion overrides were used
207-
if (TryParseJavaArtifactAndVersion ("ProjectReference", task))
199+
if (task.TryParseJavaArtifactAndJavaVersion ("ProjectReference", log, out var explicit_artifact, out var attributes_specified)) {
200+
artifacts.Add (explicit_artifact);
201+
continue;
202+
}
203+
204+
// If user tried to specify JavaArtifact or JavaVersion, but did it incorrectly, we do not perform any fallback
205+
if (attributes_specified)
208206
continue;
209207

210208
// There currently is no alternate way to figure this out. Perhaps in
@@ -228,55 +226,6 @@ public void AddIgnoredDependencies (ITaskItem []? tasks)
228226
}
229227
}
230228

231-
// "type" is PackageReference or ProjectReference
232-
// Returns "true" if JavaArtifact/JavaVersion is used, even if it was used incorrectly and is useless.
233-
// This is so the caller will know to try alternate methods if neither JavaArtifact or JavaVersion were specified.
234-
bool TryParseJavaArtifactAndVersion (string type, ITaskItem task)
235-
{
236-
var item_name = task.ItemSpec;
237-
238-
// Convert "../../src/blah/Blah.csproj" to "Blah.csproj"
239-
if (type == "ProjectReference")
240-
item_name = Path.GetFileName (item_name);
241-
242-
var has_artifact = task.HasMetadata ("JavaArtifact");
243-
var has_version = task.HasMetadata ("JavaVersion");
244-
245-
if (has_artifact && !has_version) {
246-
log.LogError ("'JavaVersion' is required when using 'JavaArtifact' for {0} '{1}'.", type, item_name);
247-
return true;
248-
}
249-
250-
if (!has_artifact && has_version) {
251-
log.LogError ("'JavaArtifact' is required when using 'JavaVersion' for {0} '{1}'.", type, item_name);
252-
return true;
253-
}
254-
255-
if (has_artifact && has_version) {
256-
var id = task.GetMetadata ("JavaArtifact");
257-
var version = task.GetMetadata ("JavaVersion");
258-
259-
if (string.IsNullOrWhiteSpace (id)) {
260-
log.LogError ("'JavaArtifact' cannot be empty for {0} '{1}'.", type, item_name);
261-
return true;
262-
}
263-
264-
if (string.IsNullOrWhiteSpace (version)) {
265-
log.LogError ("'JavaVersion' cannot be empty for {0} '{1}'.", type, item_name);
266-
return true;
267-
}
268-
269-
if (MavenExtensions.TryParseArtifactWithVersion (id, version, log, out var art)) {
270-
log.LogMessage ("Found Java dependency '{0}:{1}' version '{2}' from {3} '{4}' (JavaArtifact)", art.GroupId, art.Id, art.Version, type, item_name);
271-
artifacts.Add (art);
272-
}
273-
274-
return true;
275-
}
276-
277-
return false;
278-
}
279-
280229
bool TrySatisfyDependency (ResolvedDependency dependency)
281230
{
282231
if (!dependency.Version.HasValue ())
@@ -321,10 +270,10 @@ public MSBuildLoggingPomResolver (TaskLoggingHelper logger)
321270

322271
Artifact? RegisterFromTaskItem (ITaskItem item, string itemName, string filename)
323272
{
324-
item.TryParseJavaArtifactAndJavaVersion (itemName, logger, out var artifact);
273+
item.TryParseJavaArtifactAndJavaVersion (itemName, logger, out var artifact, out var _);
325274

326275
if (!File.Exists (filename)) {
327-
logger.LogError ("Requested POM file '{0}' does not exist.", filename);
276+
logger.LogCodedError ("XA4245", Properties.Resources.XA4245, filename);
328277
return null;
329278
}
330279

@@ -348,7 +297,7 @@ public MSBuildLoggingPomResolver (TaskLoggingHelper logger)
348297
return final_artifact;
349298
}
350299
} catch (Exception ex) {
351-
logger.LogError ("Failed to register POM file '{0}': '{1}'", filename, ex);
300+
logger.LogCodedError ("XA4246", Properties.Resources.XA4246, filename, ex.Message);
352301
return null;
353302
}
354303
}
@@ -358,7 +307,7 @@ public Project ResolveRawProject (Artifact artifact)
358307
if (poms.TryGetValue (artifact.ToString (), out var project))
359308
return project;
360309

361-
logger.LogError ("Unable to resolve POM for artifact '{0}'.", artifact);
310+
logger.LogCodedError ("XA4247", Properties.Resources.XA4247, artifact);
362311

363312
throw new InvalidOperationException ($"No POM registered for {artifact}");
364313
}
@@ -406,10 +355,10 @@ public class Package
406355

407356
public class NuGetPackageVersionFinder
408357
{
409-
LockFile lock_file;
410-
Dictionary<string, Artifact> cache = new Dictionary<string, Artifact> ();
411-
Regex tag = new Regex ("artifact_versioned=(?<GroupId>.+)?:(?<ArtifactId>.+?):(?<Version>.+)\\s?", RegexOptions.Compiled);
412-
Regex tag2 = new Regex ("artifact=(?<GroupId>.+)?:(?<ArtifactId>.+?):(?<Version>.+)\\s?", RegexOptions.Compiled);
358+
readonly LockFile lock_file;
359+
readonly Dictionary<string, Artifact> cache = new Dictionary<string, Artifact> ();
360+
readonly Regex tag = new Regex ("artifact_versioned=(?<GroupId>.+)?:(?<ArtifactId>.+?):(?<Version>.+)\\s?", RegexOptions.Compiled);
361+
readonly Regex tag2 = new Regex ("artifact=(?<GroupId>.+)?:(?<ArtifactId>.+?):(?<Version>.+)\\s?", RegexOptions.Compiled);
413362

414363
NuGetPackageVersionFinder (LockFile lockFile)
415364
{
@@ -423,7 +372,7 @@ public class NuGetPackageVersionFinder
423372
var lock_file = lock_file_format.Read (filename);
424373
return new NuGetPackageVersionFinder (lock_file);
425374
} catch (Exception e) {
426-
log.LogError (e.Message);
375+
log.LogMessage ("Could not parse NuGet lock file. Java dependencies fulfilled by NuGet packages may not be available: '{0}'.", e.Message);
427376
return null;
428377
}
429378
}
@@ -440,7 +389,7 @@ public class NuGetPackageVersionFinder
440389
var nuget = lock_file.GetLibrary (library, new NuGet.Versioning.NuGetVersion (version));
441390

442391
if (nuget is null) {
443-
log.LogError ("Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added.", library, version);
392+
log.LogCodedError ("XA4248", Properties.Resources.XA4248, library, version);
444393
return null;
445394
}
446395

@@ -636,8 +585,6 @@ public static IEnumerable<MavenVersionRange> Parse (string range)
636585
if (!range.HasValue ())
637586
yield break;
638587

639-
var versionGroups = new List<string> ();
640-
641588
// Do a pass over the range string to parse out version groups
642589
// eg: (1.0],(1.1,]
643590
var in_group = false;

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ public void AndroidMavenLibrary_FailsDueToUnverifiedDependency ()
810810
Assert.IsFalse (b.Build (proj), "Build should have failed.");
811811

812812
// Ensure an error was raised
813-
StringAssertEx.Contains ("error : Java dependency 'androidx.annotation:annotation' version '1.2.0' is not satisfied.", b.LastBuildOutput);
813+
StringAssertEx.Contains ("error XA4242: Java dependency 'androidx.annotation:annotation:1.2.0' is not satisfied.", b.LastBuildOutput);
814814
}
815815
}
816816

0 commit comments

Comments
 (0)