User: joe Date: 10 Oct 26 14:08 Revision: a8f74004aad455d823a383af72cf9e87cedae7a7 Summary: Move 2026.3 reflection into McdevReflection TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=10656&personal=false Index: src/main/kotlin/creator/custom/CreatorCredentials.kt =================================================================== --- src/main/kotlin/creator/custom/CreatorCredentials.kt (revision 9a0a9ba8cdbbb536dbd9c4621b4e4e731bdf3109) +++ src/main/kotlin/creator/custom/CreatorCredentials.kt (revision a8f74004aad455d823a383af72cf9e87cedae7a7) @@ -22,6 +22,8 @@ import com.demonwav.mcdev.MinecraftSettings import com.demonwav.mcdev.creator.custom.providers.RemoteTemplateProvider.RemoteAuthType +import com.demonwav.mcdev.util.McdevReflection +import com.demonwav.mcdev.util.McdevReflection.invokeUnwrap import com.github.kittinunf.fuel.core.Request import com.github.kittinunf.fuel.core.extensions.authentication import com.intellij.collaboration.auth.AccountManager @@ -33,7 +35,6 @@ import com.intellij.ide.passwordSafe.PasswordSafe import git4idea.remote.GitHttpAuthDataProvider import git4idea.remote.hosting.http.SilentHostedGitHttpAuthDataProviderBase -import java.lang.reflect.Method import java.nio.file.Path import java.util.Properties import javax.xml.parsers.DocumentBuilderFactory @@ -44,13 +45,6 @@ import kotlin.io.path.inputStream object CreatorCredentials { - private val PROVIDER_ID_PROPERTY: Method = SilentHostedGitHttpAuthDataProviderBase::class.java - .getDeclaredMethod("getProviderId") - .also { it.isAccessible = true } - private val ACCOUNT_MANAGER_PROPERTY: Method = SilentHostedGitHttpAuthDataProviderBase::class.java - .getDeclaredMethod("getAccountManager") - .also { it.isAccessible = true } - private val xmlDocumentBuilder = DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder() private val xPath = XPathFactory.newDefaultInstance().newXPath() @@ -118,12 +112,15 @@ return request } - fun SilentHostedGitHttpAuthDataProviderBase<*, *>.getProviderId(): String - = PROVIDER_ID_PROPERTY.invoke(this) as String + fun SilentHostedGitHttpAuthDataProviderBase<*, *>.getProviderId(): String = + McdevReflection.Git4Idea.METHOD_SILENT_HOSTED_GIT_HTTP_AUTH_DATA_PROVIDER_BASE_GET_PROVIDER_ID + .invokeUnwrap(this) as String @Suppress("UNCHECKED_CAST") - private fun SilentHostedGitHttpAuthDataProviderBase.getAccountManager(): AccountManager - = ACCOUNT_MANAGER_PROPERTY.invoke(this) as AccountManager + private fun SilentHostedGitHttpAuthDataProviderBase.getAccountManager(): + AccountManager = + McdevReflection.Git4Idea.METHOD_SILENT_HOSTED_GIT_HTTP_AUTH_DATA_PROVIDER_BASE_GET_ACCOUNT_MANAGER + .invokeUnwrap(this) as AccountManager fun getGitHttpAuthProviders(): List> { return GitHttpAuthDataProvider.EP_NAME.extensionList Index: src/main/kotlin/util/McdevReflection.kt =================================================================== --- src/main/kotlin/util/McdevReflection.kt (revision 9a0a9ba8cdbbb536dbd9c4621b4e4e731bdf3109) +++ src/main/kotlin/util/McdevReflection.kt (revision a8f74004aad455d823a383af72cf9e87cedae7a7) @@ -22,10 +22,12 @@ import com.intellij.codeInsight.generation.ClassMember import com.intellij.codeInsight.generation.GenerateMembersHandlerBase +import com.intellij.collaboration.auth.AccountManager import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.openapi.updateSettings.impl.PluginDownloader import com.intellij.psi.PsiClass +import git4idea.remote.hosting.http.SilentHostedGitHttpAuthDataProviderBase import java.lang.reflect.Field import java.lang.reflect.InvocationTargetException import java.lang.reflect.Method @@ -68,6 +70,26 @@ PluginDownloader::class.java.getDeclaredFieldEx("myFile", Path::class.java) /** + * Members from the Git4Idea plugin. Kept in a separate object so that they are only initialized when needed, and a + * missing Git4Idea plugin doesn't break the rest of [McdevReflection]. + */ + object Git4Idea { + @JvmStatic + val METHOD_SILENT_HOSTED_GIT_HTTP_AUTH_DATA_PROVIDER_BASE_GET_PROVIDER_ID: Method = + SilentHostedGitHttpAuthDataProviderBase::class.java + .getDeclaredMethodEx("getProviderId", String::class.java) + + @JvmStatic + val METHOD_SILENT_HOSTED_GIT_HTTP_AUTH_DATA_PROVIDER_BASE_GET_ACCOUNT_MANAGER: Method = + SilentHostedGitHttpAuthDataProviderBase::class.java + .getDeclaredMethodEx("getAccountManager", AccountManager::class.java) + + fun initialize() { + // load the class, used for testing + } + } + + /** * Like [Class.getDeclaredField], but makes the field accessible and checks that it has the expected [type]. */ private fun Class<*>.getDeclaredFieldEx(name: String, type: Class<*>): Field { Index: src/test/kotlin/util/McdevReflectionTest.kt =================================================================== --- src/test/kotlin/util/McdevReflectionTest.kt (revision 9a0a9ba8cdbbb536dbd9c4621b4e4e731bdf3109) +++ src/test/kotlin/util/McdevReflectionTest.kt (revision a8f74004aad455d823a383af72cf9e87cedae7a7) @@ -33,4 +33,11 @@ // them can't be found. assertDoesNotThrow { McdevReflection.initialize() } } + + @Test + @DisplayName("Reflected Git4Idea members exist") + fun reflectedGit4IdeaMembersExist() { + // McdevReflection.Git4Idea is initialized separately from McdevReflection, so must be tested separately. + assertDoesNotThrow { McdevReflection.Git4Idea.initialize() } -} + } +}