-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Java.Interop.Tools.Maven] Initial commit. #1179
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
2b1dd0a
[Java.Interop.Tools.Maven] Initial commit.
jpobst 624f8a5
Remove obsolete file.
jpobst 726b72c
Address review feedback.
jpobst dd7d720
Move MavenVersion and MavenVersionRange from XABT.
jpobst 77087b7
Address review feedback.
jpobst c7ea62c
Merge branch 'main' into java-interop-maven
jpobst 107a9d4
Add target for generating `Project.cs`.
jpobst 7a2b105
Whitespace updates.
jonpryor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Java.Interop.Tools.Maven.Models; | ||
|
||
namespace Java.Interop.Tools.Maven; | ||
|
||
public class DefaultProjectResolver : IProjectResolver | ||
{ | ||
readonly Dictionary<string, Project> poms = new (); | ||
|
||
public void Register (Project project) | ||
{ | ||
poms.Add (project.VersionedArtifactString, project); | ||
} | ||
|
||
public virtual Project Resolve (Artifact artifact) | ||
{ | ||
if (poms.TryGetValue (artifact.VersionedArtifactString, out var project)) | ||
return project; | ||
|
||
throw new InvalidOperationException ($"No POM registered for {artifact}"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using System.Collections.Generic; | ||
using System.Collections.ObjectModel; | ||
using System.Xml.Linq; | ||
using Java.Interop.Tools.Maven.Models; | ||
|
||
namespace Java.Interop.Tools.Maven.Extensions; | ||
|
||
class PropertyStack | ||
{ | ||
// Why go to this trouble? | ||
// A property can be specified in both a child POM and its parent POM. | ||
// Even if the property is being consumed in the parent POM, the property in | ||
// the child POM takes precedence. | ||
readonly List<List<KeyValuePair<string, string>>> stack = new (); | ||
|
||
public void Push (ModelProperties? properties) | ||
{ | ||
// We add a new list to the stack, even if it's empty, so that the Pop works later | ||
var list = new List<KeyValuePair<string, string>> (); | ||
|
||
if (properties?.Any is Collection<XElement> props) | ||
foreach (var prop in props) | ||
list.Add (new KeyValuePair<string, string> (prop.Name.LocalName, prop.Value)); | ||
|
||
stack.Add (list); | ||
} | ||
|
||
public void Pop () | ||
{ | ||
stack.RemoveAt (stack.Count - 1); | ||
} | ||
|
||
public string Apply (string value) | ||
{ | ||
if (stack.Count == 0 || !value.Contains ("${")) | ||
return value; | ||
|
||
foreach (var property_set in stack) { | ||
foreach (var prop in property_set) | ||
value = value.Replace ($"${{{prop.Key}}}", prop.Value); | ||
} | ||
|
||
return value; | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
src/Java.Interop.Tools.Maven/Extensions/StringExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
using System.Diagnostics.CodeAnalysis; | ||
|
||
namespace Java.Interop.Tools.Maven.Extensions; | ||
|
||
static class StringExtensions | ||
{ | ||
/// <summary> | ||
/// Shortcut for !string.IsNullOrWhiteSpace (s) | ||
/// </summary> | ||
public static bool HasValue ([NotNullWhen (true)] this string? s) => !string.IsNullOrWhiteSpace (s); | ||
|
||
/// <summary> | ||
/// Shortcut for s ?? string.Empty | ||
/// </summary> | ||
public static string OrEmpty (this string? str) => str ?? string.Empty; | ||
|
||
/// <summary> | ||
/// Removes the first subset of a delimited string. ("127.0.0.1" -> "0.0.1") | ||
/// </summary> | ||
[return: NotNullIfNotNull (nameof (s))] | ||
public static string? ChompFirst (this string? s, char separator) | ||
{ | ||
if (!s.HasValue ()) | ||
return s; | ||
|
||
var index = s.IndexOf (separator); | ||
|
||
if (index < 0) | ||
return string.Empty; | ||
|
||
return s.Substring (index + 1); | ||
} | ||
|
||
/// <summary> | ||
/// Removes the final subset of a delimited string. ("127.0.0.1" -> "127.0.0") | ||
/// </summary> | ||
[return: NotNullIfNotNull (nameof (s))] | ||
public static string? ChompLast (this string? s, char separator) | ||
{ | ||
if (!s.HasValue ()) | ||
return s; | ||
|
||
var index = s.LastIndexOf (separator); | ||
|
||
if (index < 0) | ||
return string.Empty; | ||
|
||
return s.Substring (0, index); | ||
} | ||
|
||
/// <summary> | ||
/// Returns the first subset of a delimited string. ("127.0.0.1" -> "127") | ||
/// </summary> | ||
[return: NotNullIfNotNull (nameof (s))] | ||
public static string? FirstSubset (this string? s, char separator) | ||
{ | ||
if (!s.HasValue ()) | ||
return s; | ||
|
||
var index = s.IndexOf (separator); | ||
|
||
if (index < 0) | ||
return s; | ||
|
||
return s.Substring (0, index); | ||
} | ||
|
||
/// <summary> | ||
/// Returns the final subset of a delimited string. ("127.0.0.1" -> "1") | ||
/// </summary> | ||
[return: NotNullIfNotNull (nameof (s))] | ||
public static string? LastSubset (this string? s, char separator) | ||
{ | ||
if (!s.HasValue ()) | ||
return s; | ||
|
||
var index = s.LastIndexOf (separator); | ||
|
||
if (index < 0) | ||
return s; | ||
|
||
return s.Substring (index + 1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
using Java.Interop.Tools.Maven.Models; | ||
|
||
namespace Java.Interop.Tools.Maven; | ||
|
||
public interface IProjectResolver | ||
{ | ||
Project Resolve (Artifact artifact); | ||
} |
28 changes: 28 additions & 0 deletions
28
src/Java.Interop.Tools.Maven/Java.Interop.Tools.Maven.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netstandard2.0</TargetFramework> | ||
<LangVersion>11.0</LangVersion> | ||
<Nullable>enable</Nullable> | ||
<DefineConstants>INTERNAL_NULLABLE_ATTRIBUTES</DefineConstants> | ||
<Nullable>enable</Nullable> | ||
<SignAssembly>true</SignAssembly> | ||
<AssemblyOriginatorKeyFile>..\..\product.snk</AssemblyOriginatorKeyFile> | ||
</PropertyGroup> | ||
|
||
<Import Project="..\..\TargetFrameworkDependentValues.props" /> | ||
|
||
<PropertyGroup> | ||
<OutputPath>$(UtilityOutputFullPath)</OutputPath> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<Compile Include="..\utils\NullableAttributes.cs" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" /> | ||
</ItemGroup> | ||
|
||
<Import Project="Java.Interop.Tools.Maven.targets" /> | ||
</Project> |
42 changes: 42 additions & 0 deletions
42
src/Java.Interop.Tools.Maven/Java.Interop.Tools.Maven.targets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<Project> | ||
<UsingTask AssemblyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\Java.Interop.BootstrapTasks.dll" TaskName="Java.Interop.BootstrapTasks.ReplaceFileContents" /> | ||
|
||
<!-- This target generates the Project model from the Maven POM schema. | ||
Prerequisites: | ||
- Install dotnet tool: 'dotnet tool install -g dotnet-xscgen' | ||
- Download new schema to this directory (eg: https://maven.apache.org/xsd/maven-4.0.0.xsd) | ||
Run 'dotnet build -t:UpdateProjectSchema -p:MavenXsd=maven-4.0.0.xsd' --> | ||
<Target Name="UpdateProjectSchema"> | ||
|
||
<PropertyGroup> | ||
<MavenXsd Condition=" '$(MavenXsd)' == '' ">maven-4.0.0.xsd</MavenXsd> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<_XscgenOpt Include="$(MavenXsd)" /> | ||
<_XscgenOpt Include="--namespace http://maven.apache.org/POM/4.0.0=Java.Interop.Tools.Maven.Models" /> | ||
<_XscgenOpt Include="--typeNameSubstitute T:Model=Project" /> | ||
<_XscgenOpt Include="--nullable" /> | ||
<_XscgenOpt Include="--pcl" /> | ||
<_XscgenOpt Include="--netCore" /> | ||
<_XscgenOpt Include="--nullableReferenceAttributes" /> | ||
<_XscgenOpt Include="-o "Models"" /> | ||
</ItemGroup> | ||
|
||
<Exec Command="xscgen @(_XscgenOpt, ' ')" /> | ||
|
||
<!-- Remove the Namespace from eg: [System.Xml.Serialization.XmlRootAttribute("project", Namespace="http://maven.apache.org/POM/4.0.0")] | ||
This allows us to import POM files that do not specify an XML namespace (xmlns). --> | ||
<ItemGroup> | ||
<Replacements Include=', Namespace="http://maven.apache.org/POM/4.0.0"' Replacement="" /> | ||
</ItemGroup> | ||
|
||
<ReplaceFileContents | ||
TemplateFile="Models/Java.Interop.Tools.Maven.Models.cs" | ||
OutputFile="Models/Project.cs" | ||
Replacements="@(Replacements)" | ||
/> | ||
|
||
<Delete Files="Models/Java.Interop.Tools.Maven.Models.cs" /> | ||
</Target> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using System; | ||
using System.Diagnostics.CodeAnalysis; | ||
|
||
namespace Java.Interop.Tools.Maven.Models; | ||
|
||
public class Artifact | ||
{ | ||
public string GroupId { get; } | ||
|
||
public string Id { get; } | ||
|
||
public string Version { get; } | ||
|
||
public string ArtifactString => $"{GroupId}:{Id}"; | ||
|
||
// Format should match Project.ArtifactString for comparisons. | ||
public string VersionedArtifactString => $"{GroupId}:{Id}:{Version}"; | ||
|
||
public Artifact (string groupId, string artifactId, string version) | ||
{ | ||
Id = artifactId; | ||
GroupId = groupId; | ||
Version = version; | ||
} | ||
|
||
public static Artifact Parse (string value) | ||
{ | ||
if (TryParse (value, out var artifact)) | ||
return artifact; | ||
|
||
throw new ArgumentException ($"Invalid artifact format: {value}"); | ||
} | ||
|
||
public static bool TryParse (string value, [NotNullWhen (true)]out Artifact? artifact) | ||
{ | ||
artifact = null; | ||
|
||
var parts = value.Split (':'); | ||
|
||
if (parts.Length != 3) | ||
return false; | ||
|
||
artifact = new Artifact (parts [0], parts [1], parts [2]); | ||
|
||
return true; | ||
} | ||
|
||
public override string ToString () => VersionedArtifactString; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using Java.Interop.Tools.Maven.Extensions; | ||
|
||
namespace Java.Interop.Tools.Maven.Models; | ||
|
||
public partial class Dependency | ||
{ | ||
public Artifact ToArtifact () | ||
=> new Artifact (GroupId.OrEmpty (), ArtifactId.OrEmpty (), Version.OrEmpty ()); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This gives me some concern, if only because this could produce lots of garbage, all depending on
stack
.I think I'd prefer a "optimization check" + use of
StringBuilder.Replace()
:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added the optimization check. 👍
From my research looking at POM files, this code will rarely be hit with the optimization check, and when it is hit it will generally be for small numbers of properties. The general guidance seems to be that
string.Replace
is faster thanStringBuilder.Replace
for small numbers of replaces, despite the extra garbage, as it avoids the overhead of creating theStringBuilder
and converting itToString
at the end.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't recall reading the guidance about "
string.Replace
is faster … for small numbers of replace". Would be interesting to read more.