Implemented more general scheme of post-processing with intentions in J2K + added replacement of get/set with property access there
This commit is contained in:
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.intentions
|
package org.jetbrains.kotlin.idea.intentions
|
||||||
|
|
||||||
import com.intellij.codeInspection.ProblemHighlightType
|
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||||
@@ -28,7 +27,6 @@ import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
|||||||
import org.jetbrains.kotlin.idea.core.getResolutionScope
|
import org.jetbrains.kotlin.idea.core.getResolutionScope
|
||||||
import org.jetbrains.kotlin.idea.core.isVisible
|
import org.jetbrains.kotlin.idea.core.isVisible
|
||||||
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
|
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
||||||
@@ -49,6 +47,10 @@ class UsePropertyAccessSyntaxIntention : JetSelfTargetingOffsetIndependentIntent
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun applyTo(element: JetCallExpression, editor: Editor) {
|
override fun applyTo(element: JetCallExpression, editor: Editor) {
|
||||||
|
applyTo(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun applyTo(element: JetCallExpression) {
|
||||||
val propertyName = findExtensionPropertyToUse(element)!!.getName()
|
val propertyName = findExtensionPropertyToUse(element)!!.getName()
|
||||||
val arguments = element.getValueArguments()
|
val arguments = element.getValueArguments()
|
||||||
when (arguments.size()) {
|
when (arguments.size()) {
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* 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 org.jetbrains.kotlin.idea.j2k
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.intentions.*
|
||||||
|
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfThenToElvisIntention
|
||||||
|
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfThenToSafeAccessIntention
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
interface J2kPostProcessing {
|
||||||
|
fun createAction(element: JetElement): (() -> Unit)?
|
||||||
|
}
|
||||||
|
|
||||||
|
object J2KPostProcessingRegistrar {
|
||||||
|
private val _processings = ArrayList<J2kPostProcessing>()
|
||||||
|
|
||||||
|
val processings: Collection<J2kPostProcessing>
|
||||||
|
get() = _processings
|
||||||
|
|
||||||
|
init {
|
||||||
|
_processings.add(RemoveExplicitTypeArgumentsProcessing())
|
||||||
|
_processings.add(MoveLambdaOutsideParenthesesProcessing())
|
||||||
|
_processings.add(ConvertToStringTemplateProcessing())
|
||||||
|
|
||||||
|
registerTypicalIntentionBasedProcessing(UsePropertyAccessSyntaxIntention()) { applyTo(it) }
|
||||||
|
registerTypicalIntentionBasedProcessing(IfThenToSafeAccessIntention()) { applyTo(it) }
|
||||||
|
registerTypicalIntentionBasedProcessing(IfThenToElvisIntention()) { applyTo(it) }
|
||||||
|
registerTypicalIntentionBasedProcessing(IfNullToElvisIntention()) { applyTo(it) }
|
||||||
|
registerTypicalIntentionBasedProcessing(SimplifyNegatedBinaryExpressionIntention()) { applyTo(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified TElement : JetElement, TIntention: JetSelfTargetingRangeIntention<TElement>> registerTypicalIntentionBasedProcessing(
|
||||||
|
intention: TIntention,
|
||||||
|
inlineOptions(InlineOption.ONLY_LOCAL_RETURN) apply: TIntention.(TElement) -> Unit
|
||||||
|
) {
|
||||||
|
_processings.add(object : J2kPostProcessing {
|
||||||
|
override fun createAction(element: JetElement): (() -> Unit)? {
|
||||||
|
if (!javaClass<TElement>().isInstance(element)) return null
|
||||||
|
@suppress("UNCHECKED_CAST")
|
||||||
|
if (intention.applicabilityRange(element as TElement) == null) return null
|
||||||
|
return { intention.apply(element) }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RemoveExplicitTypeArgumentsProcessing : J2kPostProcessing {
|
||||||
|
override fun createAction(element: JetElement): (() -> Unit)? {
|
||||||
|
if (element !is JetTypeArgumentList || !RemoveExplicitTypeArgumentsIntention.isApplicableTo(element, approximateFlexible = true)) return null
|
||||||
|
|
||||||
|
return { element.delete() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MoveLambdaOutsideParenthesesProcessing : J2kPostProcessing {
|
||||||
|
private val intention = MoveLambdaOutsideParenthesesIntention()
|
||||||
|
|
||||||
|
override fun createAction(element: JetElement): (() -> Unit)? {
|
||||||
|
if (element !is JetCallExpression) return null
|
||||||
|
val literalArgument = element.valueArguments.lastOrNull()?.getArgumentExpression()?.unpackFunctionLiteral() ?: return null
|
||||||
|
if (!intention.isApplicableTo(element, literalArgument.textOffset)) return null
|
||||||
|
return { intention.applyTo(element) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ConvertToStringTemplateProcessing : J2kPostProcessing {
|
||||||
|
private val intention = ConvertToStringTemplateIntention()
|
||||||
|
|
||||||
|
override fun createAction(element: JetElement): (() -> Unit)? {
|
||||||
|
if (element is JetBinaryExpression && intention.isApplicableTo(element) && intention.isConversionResultSimple(element)) {
|
||||||
|
return { intention.applyTo(element) }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,16 +19,15 @@ package org.jetbrains.kotlin.idea.j2k
|
|||||||
import com.intellij.openapi.editor.RangeMarker
|
import com.intellij.openapi.editor.RangeMarker
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiRecursiveElementVisitor
|
||||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||||
import com.intellij.psi.search.LocalSearchScope
|
import com.intellij.psi.search.LocalSearchScope
|
||||||
import com.intellij.psi.search.searches.ReferencesSearch
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
|
import com.intellij.util.SmartList
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||||
import org.jetbrains.kotlin.idea.intentions.*
|
|
||||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfThenToElvisIntention
|
|
||||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfThenToSafeAccessIntention
|
|
||||||
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
|
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
|
||||||
import org.jetbrains.kotlin.idea.quickfix.RemoveRightPartOfBinaryExpressionFix
|
import org.jetbrains.kotlin.idea.quickfix.RemoveRightPartOfBinaryExpressionFix
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
@@ -38,7 +37,8 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import java.util.ArrayList
|
import java.util.HashSet
|
||||||
|
import java.util.LinkedHashMap
|
||||||
|
|
||||||
public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
||||||
override fun analyzeFile(file: JetFile, range: TextRange?): BindingContext {
|
override fun analyzeFile(file: JetFile, range: TextRange?): BindingContext {
|
||||||
@@ -90,101 +90,25 @@ public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun doAdditionalProcessing(file: JetFile, rangeMarker: RangeMarker?) {
|
override fun doAdditionalProcessing(file: JetFile, rangeMarker: RangeMarker?) {
|
||||||
fun rangeFilter(element: PsiElement): RangeFilterResult {
|
var elementToActions = collectAvailableActions(file, rangeMarker)
|
||||||
if (rangeMarker == null) return RangeFilterResult.PROCESS
|
|
||||||
if (!rangeMarker.isValid()) return RangeFilterResult.SKIP
|
|
||||||
val range = TextRange(rangeMarker.getStartOffset(), rangeMarker.getEndOffset())
|
|
||||||
val elementRange = element.getTextRange()
|
|
||||||
return when {
|
|
||||||
range.contains(elementRange) -> RangeFilterResult.PROCESS
|
|
||||||
range.intersects(elementRange) -> RangeFilterResult.GO_INSIDE
|
|
||||||
else -> RangeFilterResult.SKIP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val redundantTypeArgs = ArrayList<JetTypeArgumentList>()
|
while (elementToActions.isNotEmpty()) {
|
||||||
file.accept(object : JetTreeVisitorVoid(){
|
val processingsToRerun = HashSet<J2kPostProcessing>()
|
||||||
override fun visitElement(element: PsiElement) {
|
|
||||||
if (rangeFilter(element) != RangeFilterResult.SKIP) {
|
|
||||||
super.visitElement(element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitTypeArgumentList(typeArgumentList: JetTypeArgumentList) {
|
for ((element, actions) in elementToActions) {
|
||||||
if (rangeFilter(typeArgumentList) == RangeFilterResult.PROCESS && RemoveExplicitTypeArgumentsIntention.isApplicableTo(typeArgumentList, approximateFlexible = true)) {
|
for ((action, processing) in actions) {
|
||||||
redundantTypeArgs.add(typeArgumentList)
|
if (element.isValid) {
|
||||||
return
|
action()
|
||||||
}
|
|
||||||
|
|
||||||
super.visitTypeArgumentList(typeArgumentList)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitPrefixExpression(expression: JetPrefixExpression) {
|
|
||||||
super.visitPrefixExpression(expression)
|
|
||||||
|
|
||||||
val intention = SimplifyNegatedBinaryExpressionIntention()
|
|
||||||
if (rangeFilter(expression) == RangeFilterResult.PROCESS && intention.isApplicableTo(expression)) {
|
|
||||||
intention.applyTo(expression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitIfExpression(expression: JetIfExpression) {
|
|
||||||
super.visitIfExpression(expression)
|
|
||||||
|
|
||||||
if (rangeFilter(expression) == RangeFilterResult.PROCESS) {
|
|
||||||
run {
|
|
||||||
val intention = IfThenToSafeAccessIntention()
|
|
||||||
if (intention.isApplicableTo(expression)) {
|
|
||||||
intention.applyTo(expression)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
run {
|
processingsToRerun.add(processing)
|
||||||
val intention = IfThenToElvisIntention()
|
|
||||||
if (intention.isApplicableTo(expression)) {
|
|
||||||
intention.applyTo(expression)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
run {
|
|
||||||
val intention = IfNullToElvisIntention()
|
|
||||||
if (intention.applicabilityRange(expression) != null) {
|
|
||||||
intention.applyTo(expression)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitBinaryExpression(expression: JetBinaryExpression) {
|
|
||||||
val intention = ConvertToStringTemplateIntention()
|
|
||||||
if (intention.isApplicableTo(expression) && intention.isConversionResultSimple(expression)) {
|
|
||||||
val result = intention.applyTo(expression)
|
|
||||||
result.accept(this)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
super.visitBinaryExpression(expression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitCallExpression(expression: JetCallExpression) {
|
|
||||||
super.visitCallExpression(expression)
|
|
||||||
|
|
||||||
val literalArgument = expression.valueArguments.lastOrNull()?.getArgumentExpression()?.unpackFunctionLiteral()
|
|
||||||
if (literalArgument != null) {
|
|
||||||
val intention = MoveLambdaOutsideParenthesesIntention()
|
|
||||||
if (intention.isApplicableTo(expression, literalArgument.textOffset)) {
|
|
||||||
intention.applyTo(expression)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
for (typeArgs in redundantTypeArgs) {
|
if (processingsToRerun.isEmpty()) break
|
||||||
typeArgs.delete()
|
//TODO: it looks like there are no such cases currently, add tests later on or drop this
|
||||||
|
elementToActions = collectAvailableActions(file, rangeMarker, processingFilter = { it in processingsToRerun })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formatCode) {
|
if (formatCode) {
|
||||||
@@ -200,5 +124,50 @@ public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class ActionData(val action: () -> Unit, val processing: J2kPostProcessing)
|
||||||
|
|
||||||
|
private fun collectAvailableActions(
|
||||||
|
file: JetFile,
|
||||||
|
rangeMarker: RangeMarker?,
|
||||||
|
processingFilter: (J2kPostProcessing) -> Boolean = { true }
|
||||||
|
): LinkedHashMap<JetElement, SmartList<ActionData>> {
|
||||||
|
val processings = J2KPostProcessingRegistrar.processings.filter(processingFilter)
|
||||||
|
val elementToActions = LinkedHashMap<JetElement, SmartList<ActionData>>()
|
||||||
|
|
||||||
|
file.accept(object : PsiRecursiveElementVisitor(){
|
||||||
|
override fun visitElement(element: PsiElement) {
|
||||||
|
if (element is JetElement) {
|
||||||
|
val rangeResult = rangeFilter(element, rangeMarker)
|
||||||
|
if (rangeResult == RangeFilterResult.SKIP) return
|
||||||
|
|
||||||
|
super.visitElement(element)
|
||||||
|
|
||||||
|
if (rangeResult == RangeFilterResult.PROCESS) {
|
||||||
|
processings.forEach { processing ->
|
||||||
|
val action = processing.createAction(element)
|
||||||
|
if (action != null) {
|
||||||
|
elementToActions.getOrPut(element) { SmartList() }.add(ActionData(action, processing))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return elementToActions
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rangeFilter(element: PsiElement, rangeMarker: RangeMarker?): RangeFilterResult {
|
||||||
|
if (rangeMarker == null) return RangeFilterResult.PROCESS
|
||||||
|
if (!rangeMarker.isValid) return RangeFilterResult.SKIP
|
||||||
|
val range = TextRange(rangeMarker.startOffset, rangeMarker.endOffset)
|
||||||
|
val elementRange = element.textRange
|
||||||
|
return when {
|
||||||
|
range.contains(elementRange) -> RangeFilterResult.PROCESS
|
||||||
|
range.intersects(elementRange) -> RangeFilterResult.GO_INSIDE
|
||||||
|
else -> RangeFilterResult.SKIP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun simpleNameReference(nameExpression: JetSimpleNameExpression) = nameExpression.mainReference
|
override fun simpleNameReference(nameExpression: JetSimpleNameExpression) = nameExpression.mainReference
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+3
@@ -49,6 +49,9 @@ public enum E {
|
|||||||
|
|
||||||
public class Base {
|
public class Base {
|
||||||
public @Nullable String foo(@Nullable String s) { return s; }
|
public @Nullable String foo(@Nullable String s) { return s; }
|
||||||
|
|
||||||
|
public int getProperty() { return 1; }
|
||||||
|
public void setProperty(int value) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Derived extends Base {
|
public class Derived extends Base {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import java.io.File
|
|||||||
|
|
||||||
class C {
|
class C {
|
||||||
fun foo(file: File): String {
|
fun foo(file: File): String {
|
||||||
val parent = file.getParentFile() ?: return ""
|
val parent = file.parentFile ?: return ""
|
||||||
return parent.getName()
|
return parent.getName()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
import javaApi.Base;
|
||||||
|
|
||||||
|
class C extends Base {
|
||||||
|
public void f() {
|
||||||
|
Base other = Base();
|
||||||
|
int value = other.getProperty() + getProperty();
|
||||||
|
other.setProperty(1);
|
||||||
|
setProperty(other.getProperty() + value);
|
||||||
|
getBase(getProperty()).setProperty(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Base getBase(int i) {
|
||||||
|
return new Base();
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
import javaApi.Base
|
||||||
|
|
||||||
|
class C : Base() {
|
||||||
|
public fun f() {
|
||||||
|
val other = Base()
|
||||||
|
val value = other.property + property
|
||||||
|
other.property = 1
|
||||||
|
property = other.property + value
|
||||||
|
getBase(property).property = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBase(i: Int): Base {
|
||||||
|
return Base()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -990,6 +990,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
|||||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/codeSimplifications/RedundantTypeCastAndInline.java");
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/codeSimplifications/RedundantTypeCastAndInline.java");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SyntheticExtensionPropertyAccess.java")
|
||||||
|
public void testSyntheticExtensionPropertyAccess() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/codeSimplifications/SyntheticExtensionPropertyAccess.java");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("j2k/testData/fileOrElement/comments")
|
@TestMetadata("j2k/testData/fileOrElement/comments")
|
||||||
|
|||||||
@@ -990,6 +990,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
|||||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/codeSimplifications/RedundantTypeCastAndInline.java");
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/codeSimplifications/RedundantTypeCastAndInline.java");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SyntheticExtensionPropertyAccess.java")
|
||||||
|
public void testSyntheticExtensionPropertyAccess() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/codeSimplifications/SyntheticExtensionPropertyAccess.java");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("j2k/testData/fileOrElement/comments")
|
@TestMetadata("j2k/testData/fileOrElement/comments")
|
||||||
|
|||||||
Reference in New Issue
Block a user