Browse Source

[Do not merge] Better sync with original code and support module filtering

compose-tooling
Ilya Ryzhenkov 2 years ago
parent
commit
4f23e2dc65
  1. 8
      idea-plugin/build.gradle.kts
  2. 10
      idea-plugin/src/main/kotlin/com/android/tools/compose/ComposableAnnotator.kt
  3. 3
      idea-plugin/src/main/kotlin/com/android/tools/compose/ComposeDiagnosticSuppressor.kt
  4. 3
      idea-plugin/src/main/kotlin/com/android/tools/compose/ComposeFoldingBuilder.kt
  5. 35
      idea-plugin/src/main/kotlin/com/android/tools/compose/ComposePluginIrGenerationExtension.kt
  6. 2
      idea-plugin/src/main/kotlin/com/android/tools/compose/ComposePluginUtils.kt
  7. 4
      idea-plugin/src/main/kotlin/com/android/tools/compose/code/completion/ComposeImplementationsCompletionContributor.kt
  8. 8
      idea-plugin/src/main/kotlin/com/android/tools/compose/code/completion/ComposeModifierCompletionContributor.kt
  9. 37
      idea-plugin/src/main/kotlin/com/android/tools/compose/debug/ComposePositionManager.kt
  10. 8
      idea-plugin/src/main/kotlin/com/android/tools/compose/formatting/ComposePostFormatProcessor.kt
  11. 32
      idea-plugin/src/main/kotlin/com/android/tools/compose/settings/ComposeCustomCodeStyleSettings.java
  12. 31
      idea-plugin/src/main/kotlin/com/android/tools/compose/settings/ComposeCustomCodeStyleSettings.kt
  13. 21
      idea-plugin/src/main/kotlin/com/android/tools/modules/Module.kt
  14. 1
      idea-plugin/src/main/resources/META-INF/plugin.xml

8
idea-plugin/build.gradle.kts

@ -12,6 +12,12 @@ val projectProperties = ProjectProperties(project)
group = "org.jetbrains.compose.desktop.ide"
version = projectProperties.deployVersion
sourceSets {
main {
java.srcDir("src/main/kotlin")
}
}
repositories {
mavenCentral()
}
@ -45,7 +51,7 @@ tasks {
// Set the compatibility versions to 1.8
withType<JavaCompile> {
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
targetCompatibility = "11"
}
withType<KotlinJvmCompile> {
kotlinOptions.jvmTarget = "11"

10
idea-plugin/src/main/kotlin/com/android/tools/compose/ComposableAnnotator.kt

@ -16,6 +16,7 @@
package com.android.tools.compose
import com.android.tools.modules.*
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.lang.annotation.Annotator
import com.intellij.lang.annotation.HighlightSeverity
@ -57,10 +58,11 @@ class ComposableAnnotator : Annotator {
// AnnotationHolder.currentAnnotationSession applies to a single file.
var canContainComposable = holder.currentAnnotationSession.getUserData(CAN_CONTAIN_COMPOSABLE_KEY)
if (canContainComposable == null) {
// isComposeEnabled doesn't work for library sources, we check all kt library sources files. File check only once on opening.
canContainComposable = isComposeEnabled(element) ||
(element.containingFile.virtualFile != null &&
ProjectFileIndex.getInstance(element.project).isInLibrarySource(element.containingFile.virtualFile))
// isComposeEnabled doesn't work for library sources, we check all kt library sources files. File check only once on opening.
canContainComposable = element.inComposeModule() ||
(element.containingFile.virtualFile != null &&
ProjectFileIndex.getInstance(element.project)
.isInLibrarySource(element.containingFile.virtualFile))
holder.currentAnnotationSession.putUserData(CAN_CONTAIN_COMPOSABLE_KEY, canContainComposable)
}

3
idea-plugin/src/main/kotlin/com/android/tools/compose/ComposeDiagnosticSuppressor.kt

@ -16,6 +16,7 @@
package com.android.tools.compose
import com.android.tools.modules.*
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.diagnostics.Diagnostic
@ -46,7 +47,7 @@ class ComposeDiagnosticSuppressor : DiagnosticSuppressor {
}
override fun isSuppressed(diagnostic: Diagnostic, bindingContext: BindingContext?): Boolean {
if (!isComposeEnabled(diagnostic.psiElement)) return false
if (!diagnostic.psiElement.inComposeModule()) return false
if (diagnostic.factory == Errors.NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION) {
for (entry in (
diagnostic.psiElement.parent as KtAnnotatedExpression

3
idea-plugin/src/main/kotlin/com/android/tools/compose/ComposeFoldingBuilder.kt

@ -15,6 +15,7 @@
*/
package com.android.tools.compose
import com.android.tools.modules.*
import com.intellij.lang.ASTNode
import com.intellij.lang.folding.CustomFoldingBuilder
import com.intellij.lang.folding.FoldingDescriptor
@ -33,7 +34,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
*/
class ComposeFoldingBuilder : CustomFoldingBuilder() {
override fun buildLanguageFoldRegions(descriptors: MutableList<FoldingDescriptor>, root: PsiElement, document: Document, quick: Boolean) {
if (root !is KtFile || DumbService.isDumb(root.project) || !isComposeEnabled(root)) {
if (root !is KtFile || DumbService.isDumb(root.project) || !root.inComposeModule()) {
return
}

35
idea-plugin/src/main/kotlin/com/android/tools/compose/ComposePluginIrGenerationExtension.kt

@ -0,0 +1,35 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.compose
import androidx.compose.compiler.plugins.kotlin.ComposeIrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@Suppress("INVISIBLE_REFERENCE", "EXPERIMENTAL_IS_NOT_ENABLED")
@OptIn(org.jetbrains.kotlin.extensions.internal.InternalNonStableExtensionPoints::class)
class ComposePluginIrGenerationExtension : IrGenerationExtension {
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
try {
ComposeIrGenerationExtension(reportsDestination = null,
metricsDestination = null).generate(moduleFragment, pluginContext);
} catch (t : Throwable) {
t.printStackTrace()
}
}
}

2
idea-plugin/src/main/kotlin/com/android/tools/compose/ComposePluginUtils.kt

@ -28,8 +28,6 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.supertypes
fun isComposeEnabled(element: PsiElement): Boolean = element.inComposeModule() ?: false
fun isModifierChainLongerThanTwo(element: KtElement): Boolean {
if (element.getChildrenOfType<KtDotQualifiedExpression>().isNotEmpty()) {
val fqName = element.resolveToCall(BodyResolveMode.PARTIAL)?.getReturnType()?.fqName?.asString()

4
idea-plugin/src/main/kotlin/com/android/tools/compose/code/completion/ComposeImplementationsCompletionContributor.kt

@ -22,8 +22,8 @@ import com.android.tools.compose.COMPOSE_ARRANGEMENT
import com.android.tools.compose.COMPOSE_ARRANGEMENT_HORIZONTAL
import com.android.tools.compose.COMPOSE_ARRANGEMENT_VERTICAL
import com.android.tools.compose.isClassOrExtendsClass
import com.android.tools.compose.isComposeEnabled
import com.android.tools.idea.flags.StudioFlags
import com.android.tools.modules.*
import com.intellij.codeInsight.completion.CompletionContributor
import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet
@ -67,7 +67,7 @@ class ComposeImplementationsCompletionContributor : CompletionContributor() {
override fun fillCompletionVariants(parameters: CompletionParameters, result: CompletionResultSet) {
val elementToComplete = parameters.position
if (!StudioFlags.COMPOSE_EDITOR_SUPPORT.get() || !isComposeEnabled(elementToComplete) || parameters.originalFile !is KtFile) {
if (!StudioFlags.COMPOSE_EDITOR_SUPPORT.get() || !elementToComplete.inComposeModule() || parameters.originalFile !is KtFile) {
return
}
val elementToCompleteTypeFqName = elementToComplete.argumentTypeFqName ?: elementToComplete.propertyTypeFqName

8
idea-plugin/src/main/kotlin/com/android/tools/compose/code/completion/ComposeModifierCompletionContributor.kt

@ -16,8 +16,8 @@
package com.android.tools.compose.code.completion
import com.android.tools.compose.ComposeLibraryNamespace
import com.android.tools.compose.isComposeEnabled
import com.android.tools.idea.flags.StudioFlags
import com.android.tools.modules.*
import com.intellij.codeInsight.completion.CompletionContributor
import com.intellij.codeInsight.completion.CompletionInitializationContext
import com.intellij.codeInsight.completion.CompletionParameters
@ -95,7 +95,7 @@ class ComposeModifierCompletionContributor : CompletionContributor() {
override fun fillCompletionVariants(parameters: CompletionParameters, resultSet: CompletionResultSet) {
val element = parameters.position
if (!StudioFlags.COMPOSE_EDITOR_SUPPORT.get() || !isComposeEnabled(element) || parameters.originalFile !is KtFile) {
if (!StudioFlags.COMPOSE_EDITOR_SUPPORT.get() || !element.inComposeModule() || parameters.originalFile !is KtFile) {
return
}
@ -241,8 +241,8 @@ class ComposeModifierCompletionContributor : CompletionContributor() {
val elementOnWhichMethodCalled: KtExpression = parent.safeAs<KtNameReferenceExpression>()?.getReceiverExpression() ?: return false
// Case Modifier.align().%this%, modifier.%this%
val fqName = elementOnWhichMethodCalled.resolveToCall(BodyResolveMode.PARTIAL)?.getReturnType()?.fqName ?:
// Case Modifier.%this%
elementOnWhichMethodCalled.safeAs<KtNameReferenceExpression>()?.resolve().safeAs<KtClass>()?.fqName
// Case Modifier.%this%
elementOnWhichMethodCalled.safeAs<KtNameReferenceExpression>()?.resolve().safeAs<KtClass>()?.fqName
return fqName?.asString() == modifierFqName
}

37
idea-plugin/src/main/kotlin/com/android/tools/compose/debug/ComposePositionManager.kt

@ -15,22 +15,27 @@
*/
package com.android.tools.compose.debug
import com.intellij.debugger.*
import com.intellij.debugger.engine.*
import com.intellij.debugger.engine.evaluation.*
import com.intellij.debugger.jdi.*
import com.intellij.debugger.requests.*
import com.intellij.openapi.application.*
import com.intellij.openapi.fileTypes.*
import com.intellij.util.*
import com.intellij.xdebugger.frame.*
import com.sun.jdi.*
import com.sun.jdi.request.*
import org.jetbrains.kotlin.fileClasses.*
import org.jetbrains.kotlin.idea.*
import org.jetbrains.kotlin.idea.debugger.*
import org.jetbrains.kotlin.load.kotlin.*
import org.jetbrains.kotlin.psi.*
import com.intellij.debugger.MultiRequestPositionManager
import com.intellij.debugger.NoDataException
import com.intellij.debugger.SourcePosition
import com.intellij.debugger.engine.DebugProcess
import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.PositionManagerWithMultipleStackFrames
import com.intellij.debugger.engine.evaluation.EvaluationContext
import com.intellij.debugger.jdi.StackFrameProxyImpl
import com.intellij.debugger.requests.ClassPrepareRequestor
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.fileTypes.FileType
import com.intellij.util.ThreeState
import com.intellij.xdebugger.frame.XStackFrame
import com.sun.jdi.Location
import com.sun.jdi.ReferenceType
import com.sun.jdi.request.ClassPrepareRequest
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.debugger.KotlinPositionManager
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.psi.KtFile
/**
* A PositionManager capable of setting breakpoints inside of ComposableSingleton lambdas.

8
idea-plugin/src/main/kotlin/com/android/tools/compose/formatting/ComposePostFormatProcessor.kt

@ -15,9 +15,9 @@
*/
package com.android.tools.compose.formatting
import com.android.tools.compose.isComposeEnabled
import com.android.tools.compose.isModifierChainLongerThanTwo
import com.android.tools.compose.settings.ComposeCustomCodeStyleSettings
import com.android.tools.modules.*
import com.intellij.application.options.CodeStyle
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.util.TextRange
@ -42,9 +42,9 @@ class ComposePostFormatProcessor : PostFormatProcessor {
private fun isAvailable(psiElement: PsiElement, settings: CodeStyleSettings): Boolean {
return psiElement.containingFile is KtFile &&
isComposeEnabled(psiElement) &&
!DumbService.isDumb(psiElement.project) &&
settings.getCustomSettings(ComposeCustomCodeStyleSettings::class.java).USE_CUSTOM_FORMATTING_FOR_MODIFIERS
psiElement.inComposeModule() &&
!DumbService.isDumb(psiElement.project) &&
settings.getCustomSettings(ComposeCustomCodeStyleSettings::class.java).USE_CUSTOM_FORMATTING_FOR_MODIFIERS
}
override fun processElement(source: PsiElement, settings: CodeStyleSettings): PsiElement {

32
idea-plugin/src/main/kotlin/com/android/tools/compose/settings/ComposeCustomCodeStyleSettings.java

@ -0,0 +1,32 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.compose.settings;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
// Don't convert to Kotlin due to the serialization implementation for Settings.
public class ComposeCustomCodeStyleSettings extends CustomCodeStyleSettings {
public boolean USE_CUSTOM_FORMATTING_FOR_MODIFIERS = true;
protected ComposeCustomCodeStyleSettings(CodeStyleSettings container) {
super("ComposeCustomCodeStyleSettings", container);
}
public static ComposeCustomCodeStyleSettings getInstance(CodeStyleSettings settings) {
return settings.getCustomSettings(ComposeCustomCodeStyleSettings.class);
}
}

31
idea-plugin/src/main/kotlin/com/android/tools/compose/settings/ComposeCustomCodeStyleSettings.kt

@ -1,31 +0,0 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.compose.settings
import com.intellij.configurationStore.*
import com.intellij.psi.codeStyle.*
class ComposeCustomCodeStyleSettings(settings: CodeStyleSettings) : CustomCodeStyleSettings("ComposeCustomCodeStyleSettings", settings) {
@Property(externalName = "use_custom_formatting_for_modifiers")
@JvmField
var USE_CUSTOM_FORMATTING_FOR_MODIFIERS = true
companion object {
fun getInstance(settings: CodeStyleSettings): ComposeCustomCodeStyleSettings {
return settings.getCustomSettings(ComposeCustomCodeStyleSettings::class.java)
}
}
}

21
idea-plugin/src/main/kotlin/com/android/tools/modules/Module.kt

@ -5,8 +5,23 @@
package com.android.tools.modules
import com.intellij.openapi.module.Module
import com.android.tools.compose.*
import com.intellij.openapi.module.*
import com.intellij.openapi.roots.*
import com.intellij.psi.*
import com.intellij.psi.search.*
import com.intellij.psi.util.*
import org.jetbrains.kotlin.idea.util.*
fun PsiElement.inComposeModule() = module?.isComposeModule() ?: false
fun Module.isComposeModule(): Boolean {
return CachedValuesManager.getManager(project).getCachedValue(this) {
val javaPsiFacade = JavaPsiFacade.getInstance(this.project)
val value = COMPOSABLE_FQ_NAMES.any {
javaPsiFacade.findClass(it, GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(this)) != null
}
val rootModificationTracker = ProjectRootModificationTracker.getInstance(project)
CachedValueProvider.Result.create(value, rootModificationTracker)
}
}
fun PsiElement.inComposeModule() = true
fun Module.isComposeModule() = true

1
idea-plugin/src/main/resources/META-INF/plugin.xml

@ -25,6 +25,7 @@
<quickFixContributor implementation="com.android.tools.compose.intentions.ComposeDelegateStateImportFixContributor"/>
<quickFixContributor implementation="com.android.tools.compose.intentions.ComposeUnresolvedFunctionFixContributor"/>
<additionalExtractableAnalyser implementation="com.android.tools.compose.ComposableFunctionExtractableAnalyser"/>
<irGenerationExtension implementation="com.android.tools.compose.ComposePluginIrGenerationExtension"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.kotlin.extensions.internal">

Loading…
Cancel
Save