Skip to content
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

[Bytecode] Hide Kotlin synthetic default constructors. #700

Merged
merged 2 commits into from
Aug 28, 2020

Conversation

jpobst
Copy link
Contributor

@jpobst jpobst commented Aug 27, 2020

Fixes #694.

Prevent "errors" like this from being displayed to the user by recognizing the synthetic default constructors that Kotlin generates and hiding them:

Error while processing '[Constructor] MaterialDialog(android.content.Context p0, com.afollestad.materialdialogs.DialogBehavior p1, int p2, kotlin.jvm.internal.DefaultConstructorMarker p3)' in '[Class] com.afollestad.materialdialogs.MaterialDialog': Type 'kotlin.jvm.internal.DefaultConstructorMarker' was not found.

@jpobst jpobst marked this pull request as ready for review August 28, 2020 14:08
@jpobst jpobst requested a review from jonpryor August 28, 2020 14:08
return false;

// Final parameter is DefaultConstructorMarker
if (parameters.Last ().Type.TypeSignature != "Lkotlin/jvm/internal/DefaultConstructorMarker;")
Copy link
Member

Choose a reason for hiding this comment

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

.Last() involves an IEnumerable allocation & enumeration. parameters [parameters.Length-1] would be more efficient, and in keeping with the return statement.

@jonpryor jonpryor merged commit f6c12ba into master Aug 28, 2020
@jonpryor jonpryor deleted the kotlin-defaultconstructor branch August 28, 2020 18:42
jonpryor pushed a commit that referenced this pull request Aug 31, 2020
…700)

Fixes: #694

Context: dotnet/android#3776

When using a Kotlin default constructor like:

	class MaterialDialog(
	  val windowContext: Context,
	  val dialogBehavior: DialogBehavior = DEFAULT_BEHAVIOR
	) : Dialog(windowContext, inferTheme(windowContext, dialogBehavior))
	{ ... }

Kotlin will create 2 constructors, the "real" one, and a synthetic one
denoting which constructor is the default constructor using a
`kotlin.jvm.internal.DefaultConstructorMarker` parameter:

	<constructor deprecated="not deprecated" final="false"
	    name="MaterialDialog" static="false" visibility="public"
	    bridge="false" synthetic="false"
	    jni-signature="(Landroid/content/Context;Lcom/afollestad/materialdialogs/DialogBehavior;)V">
	  <parameter name="windowContext" type="android.content.Context" jni-type="Landroid/content/Context;" not-null="true"/>
	  <parameter name="dialogBehavior" type="com.afollestad.materialdialogs.DialogBehavior" jni-type="Lcom/afollestad/materialdialogs/DialogBehavior;" not-null="true"/>
	</constructor>
	<constructor deprecated="not deprecated" final="false"
	    name="MaterialDialog" static="false" visibility="public"
	    bridge="false" synthetic="true"
	    jni-signature="(Landroid/content/Context;Lcom/afollestad/materialdialogs/DialogBehavior;ILkotlin/jvm/internal/DefaultConstructorMarker;)V">
	  <parameter name="p0" type="android.content.Context" jni-type="Landroid/content/Context;"/>
	  <parameter name="p1" type="com.afollestad.materialdialogs.DialogBehavior" jni-type="Lcom/afollestad/materialdialogs/DialogBehavior;"/>
	  <parameter name="p2" type="int" jni-type="I"/>
	  <parameter name="p3" type="kotlin.jvm.internal.DefaultConstructorMarker" jni-type="Lkotlin/jvm/internal/DefaultConstructorMarker;"/>
	</constructor>

Additionally, the `kotlin.jvm.internal.DefaultConstructorMarker` type
is not available in the `Xamarin.Kotlin.StdLib` NuGet package, because
the type is `internal`.

Consequently, when trying to bind the constructor, `ApiXmlAdjuster`
reports this "error":

	Error while processing '[Constructor] MaterialDialog(android.content.Context p0, com.afollestad.materialdialogs.DialogBehavior p1, int p2, kotlin.jvm.internal.DefaultConstructorMarker p3)' in '[Class] com.afollestad.materialdialogs.MaterialDialog': Type 'kotlin.jvm.internal.DefaultConstructorMarker' was not found.

This is actually good, as we shouldn't bind this synthetic constructor,
but we should detect this Kotlin-ism and not emit the "error", as it
misleads users into thinking they need to do something to fix it.

Update `Xamarin.Android.Tools.Bytecode` to *hide* constructors for
which the final two parameter types are `int, DefaultConstructorMarker`,
thus ensuring that `ApiXmlAdjuster` & co. won't process such members
or attempt to resolve the unresolvable `DefaultConstructorMarker` type.
@jpobst jpobst added this to the 11.0 (16.8 / 8.8) milestone Sep 3, 2020
@github-actions github-actions bot locked and limited conversation to collaborators Apr 13, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ignore binding Kotlin synthetic default constructors
2 participants