Skip to content

[Bytecode] Hide Kotlin synthetic default constructors. #700

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

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 force-pushed the kotlin-defaultconstructor branch from 4d8b8aa to 322ed90 Compare August 27, 2020 19:37
@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
Contributor

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
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ignore binding Kotlin synthetic default constructors
2 participants