Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/Java.Interop.Localization/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/Java.Interop.Localization/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ The following terms should not be translated: &lt;package&gt;.</comment>
<comment>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</comment>
</data>
<data name="Generator_BG8A07" xml:space="preserve">
<value>Invalid namespace transform '{0}'</value>
<comment>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</comment>
</data>
<data name="Generator_BG8B00" xml:space="preserve">
<value>Unknown generic argument constraint type '{0}' for member '{1}'.</value>
<comment>{0} - .NET type name
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.pt-BR.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.ru.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.tr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.zh-Hans.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Java.Interop.Localization/xlf/Resources.zh-Hant.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ The following terms should not be translated: &lt;package&gt;.</note>
<note>{0} - XML transform. (example: '&lt;remove-node path="/api/package[@name='javax.sql']"')
The following terms should not be translated: Metadata.xml.</note>
</trans-unit>
<trans-unit id="Generator_BG8A07">
<source>Invalid namespace transform '{0}'</source>
<target state="new">Invalid namespace transform '{0}'</target>
<note>{0} - XML transform. (example: '&lt;ns-replace source="example" replacement="Example" /&gt;')</note>
</trans-unit>
<trans-unit id="Generator_BG8B00">
<source>Unknown generic argument constraint type '{0}' for member '{1}'.</source>
<target state="new">Unknown generic argument constraint type '{0}' for member '{1}'.</target>
Expand Down
30 changes: 30 additions & 0 deletions src/Java.Interop.Tools.Generator/Extensions/UtilityExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
using System.Xml;
using System.Xml.Linq;

Expand Down Expand Up @@ -41,5 +43,33 @@ public static bool StartsWithAny (this string value, params string [] values)

return null;
}

// A case-insensitive Replace doesn't exist in classic .NET Framework. Loosely based on:
// https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs
public static string ReplaceOrdinalIgnoreCase (this string source, string oldValue, string newValue)
{
var result = new StringBuilder ();
var pos = 0;

while (true) {
var index = source.IndexOf (oldValue, pos, StringComparison.OrdinalIgnoreCase);

// Not found, bail
if (index < 0)
break;

// Append the unmodified portion of search space
result.Append (source.Substring (pos, index));

// Append the replacement
result.Append (newValue);

pos = index + oldValue.Length;
}

// Append what remains of the search space, then allocate the new string.
result.Append (source.Substring (pos));
return result.ToString ();
}
}
}
13 changes: 13 additions & 0 deletions src/Java.Interop.Tools.Generator/Metadata/FixupXmlDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Xml.Linq;

using Xamarin.Android.Tools;
using System.Collections.Generic;

namespace Java.Interop.Tools.Generator
{
Expand Down Expand Up @@ -168,6 +169,18 @@ public void Apply (ApiXmlDocument apiDocument, string apiLevelString, int produc
}
}

public IList<NamespaceTransform> GetNamespaceTransforms ()
{
var list = new List<NamespaceTransform> ();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a List<T>, or should it be a HashSet<T>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Order is significant, so we need to stick with List.


foreach (var xe in FixupDocument.XPathSelectElements ("/metadata/ns-replace")) {
if (NamespaceTransform.TryParse (xe, out var transform))
list.Add (transform);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should happen if there's a duplicate? Should we care? Emit a warning?

Particularly if we're thinking of adding Metadata.xml into NuGet packages for "reuse" by "downstream binding projects", the likelihood for duplicates will increase. It shouldn't be an error, but would a warning be useful? Or would it be too common for warnings?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to ignore duplicates, we do the same for other metadata.

I'm not aware of any plan to add Metadata.xml into NuGet packages.

}

return list;
}

bool ShouldSkip (XElement node, int apiLevel, int productVersion)
{
if (apiLevel > 0) {
Expand Down
123 changes: 123 additions & 0 deletions src/Java.Interop.Tools.Generator/Metadata/NamespaceTransform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Xml.Linq;
using Xamarin.Android.Tools;

namespace Java.Interop.Tools.Generator
{
public class NamespaceTransform
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rando aside: would this be a good use case for C#9 records? https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#record-types

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like you can override primary constructors (?!), so this isn't a good use case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, you can still use record types without using primary constructors…

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading through the link, I don't see any benefits to using record, and we haven't bumped to C# 9 yet.

{
public string OldValue { get; }
public string NewValue { get; }
public bool IsStartsWith { get; }
public bool IsEndsWith { get; }

public NamespaceTransform (string oldValue, string newValue)
{
OldValue = oldValue;
NewValue = newValue;

if (OldValue.EndsWith (".", StringComparison.Ordinal)) {
IsStartsWith = true;
OldValue = OldValue.Substring (0, OldValue.Length - 1);
}

if (OldValue.StartsWith (".", StringComparison.Ordinal)) {
IsEndsWith = true;
OldValue = OldValue.Substring (1);
}
}

public string ApplyInternal (string value)
{
string result;

while (true) {
result = ApplyInternal (value);

if (result == value)
return result;

value = result;
}
}

public string Apply (string value)
{
// Handle a "starts with" and "ends with" transform
if (IsStartsWith && IsEndsWith) {
if (value.Equals (OldValue, StringComparison.OrdinalIgnoreCase))
return NewValue;

// Don't let this fall through
return value;
}

// Handle a "starts with" transform
if (IsStartsWith) {
if (value.StartsWith (OldValue, StringComparison.OrdinalIgnoreCase))
return (NewValue + value.Substring (OldValue.Length)).TrimStart ('.');

return value;
}

// Handle an "ends with" transform
if (IsEndsWith) {
if (value.EndsWith (OldValue, StringComparison.OrdinalIgnoreCase))
return (value.Substring (0, value.Length - OldValue.Length) + NewValue).TrimEnd ('.');

return value;
}

// Handle an "anywhere" transform
var value_tokens = value.Split ('.');
var match_tokens = OldValue.Split ('.');

var results = new List<string> ();

for (var i = 0; i < value_tokens.Length; i++) {
if (AtMatch (value_tokens, i, match_tokens, 0)) {
if (NewValue.HasValue ())
results.Add (NewValue);

i += match_tokens.Length - 1;
} else {
results.Add (value_tokens [i]);
}
}

return string.Join (".", results);
}

public static bool TryParse (XElement element, [NotNullWhen (true)] out NamespaceTransform? transform)
{
var source = element.XGetAttribute ("source");
var replacement = element.XGetAttribute ("replacement");

if (!source.HasValue () || replacement is null) {
Report.LogCodedWarning (0, Report.WarningInvalidNamespaceTransform, null, element, element.ToString ());
transform = null;
return false;
}

transform = new NamespaceTransform (source, replacement);
return true;
}

private bool AtMatch (string [] valueTokens, int valueIndex, string [] matchTokens, int matchIndex)
{
if (matchIndex >= matchTokens.Length)
return true;

if (valueIndex >= valueTokens.Length)
return false;

if (string.Compare (valueTokens [valueIndex], matchTokens [matchIndex], StringComparison.OrdinalIgnoreCase) == 0)
return AtMatch (valueTokens, valueIndex + 1, matchTokens, matchIndex + 1);

return false;
}
}
}

1 change: 1 addition & 0 deletions src/Java.Interop.Tools.Generator/Utilities/Report.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public LocalizedMessage (int code, string value)
public static LocalizedMessage WarningAttrMatchedNoNodes => new LocalizedMessage (0x8A04, Localization.Resources.Generator_BG8A00);
public static LocalizedMessage WarningMoveNodeMatchedNoNodes => new LocalizedMessage (0x8A05, Localization.Resources.Generator_BG8A00);
public static LocalizedMessage WarningRemoveAttrMatchedNoNodes => new LocalizedMessage (0x8A06, Localization.Resources.Generator_BG8A00);
public static LocalizedMessage WarningInvalidNamespaceTransform => new LocalizedMessage (0x8A07, Localization.Resources.Generator_BG8A07);
public static LocalizedMessage WarningUnknownGenericConstraint => new LocalizedMessage (0x8B00, Localization.Resources.Generator_BG8B00);
public static LocalizedMessage WarningBaseInterfaceNotFound => new LocalizedMessage (0x8C00, Localization.Resources.Generator_BG8C00);
public static LocalizedMessage WarningBaseInterfaceInvalid => new LocalizedMessage (0x8C01, Localization.Resources.Generator_BG8C01);
Expand Down
Loading