Skip to content

Commit

Permalink
[generator] Fix exception caused by incorrect nested type name. (#1267)
Browse files Browse the repository at this point in the history
Context: #1266
Context: #1268

While the issue described in #1266 is definitely
an issue, that example was merely setting up the scenario needed to
expose another bug:

When a `Java.Lang.Object` or `Java.Interop.JavaObject` subclass
has a `public` or `internal` field whose type is a nested type:

	// C#
	namespace Com.Mypackage;

	[Register ("com/mypackage/FieldClass")]
	public class FieldClass : Java.Lang.Object {
	    public NestedFieldClass field;
	
	    public class NestedFieldClass : Java.Lang.Object {
	    }
	}

We correctly import the `Field.TypeName` as
`Com.Mypackage.FieldClass.NestedFieldClass`, however we also create
`Field.SetterParameter` with the "same" type, but we do not replace
the `/` nested type separator with a period, resulting in
`Com.Mypackage.FieldClass/NestedFieldClass`.

Later, when validating the `Field`, we successfully find
`Field.TypeName` in the symbol table, but fail to find
`Field.SetterParameter` as the symbol table expects a period nested
type separator.  (Note this only happens because `NestedFieldClass`
does not have a `[Register]` attribute, thus it gets added to the
symbol table with its managed name rather than its Java name.)

This causes `generator` to crash with:

	System.NotSupportedException: Unable to generate setter parameter list in managed type Com.Mypackage.FieldClass
	   at MonoDroid.Generation.Field.Validate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context)
	   at MonoDroid.Generation.GenBase.OnValidate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context)
	   at MonoDroid.Generation.ClassGen.OnValidate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context)
	   at MonoDroid.Generation.GenBase.Validate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context)

Fix this by applying the same `FullNameCorrected()` logic that is
applied to `Field.TypeName`.
  • Loading branch information
jpobst authored Oct 21, 2024
1 parent b656f7f commit 56cfab9
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 1 deletion.
24 changes: 24 additions & 0 deletions tests/generator-Tests/Unit-Tests/ManagedTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ public void UnknownTypes (object unknown) { }

[Register ("com/mypackage/service")]
public interface IService { }

[Register ("com/mypackage/FieldClass")]
public class FieldClass : Java.Lang.Object
{
public NestedFieldClass field;

public class NestedFieldClass : Java.Lang.Object { }
}

}

namespace GenericTestClasses
Expand Down Expand Up @@ -133,6 +142,21 @@ public void Class ()
Assert.IsNull (@class.DeprecatedComment);
}

[Test]
public void FieldWithNestedType ()
{
var @class = CecilApiImporter.CreateClass (module.GetType ("Com.Mypackage.FieldClass"), options);
var @class2 = CecilApiImporter.CreateClass (module.GetType ("Com.Mypackage.FieldClass/NestedFieldClass"), options);

options.SymbolTable.AddType (@class);
options.SymbolTable.AddType (@class2);

Assert.IsTrue (@class.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "@class.Validate failed!");

// Ensure the front slash is replaced with a period
Assert.AreEqual ("Com.Mypackage.FieldClass.NestedFieldClass", @class.Fields [0].TypeName);
}

[Test]
public void Method ()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ public static Field CreateField (FieldDefinition f)
Visibility = f.IsPublic ? "public" : f.IsFamilyOrAssembly ? "protected internal" : f.IsFamily ? "protected" : f.IsAssembly ? "internal" : "private"
};

field.SetterParameter = CreateParameter (f.FieldType.Resolve ()?.FullName ?? f.FieldType.FullName, null);
var field_parameter_type = f.FieldType.Resolve () ?? f.FieldType;
field.SetterParameter = CreateParameter (field_parameter_type.FullNameCorrected ().StripArity (), null);
field.SetterParameter.Name = "value";

return field;
Expand Down

0 comments on commit 56cfab9

Please sign in to comment.