diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DataClassUtils.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DataClassUtils.kt new file mode 100644 index 00000000000..b00e15148d3 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DataClassUtils.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2014 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.jet.lang.resolve.dataClassUtils + +import org.jetbrains.jet.lang.resolve.name.Name +import java.util.regex.Pattern + +private val COMPONENT_FUNCTION_NAME_PREFIX = "component" + +public fun isComponentLike(name: Name): Boolean { + if (!name.asString().startsWith(COMPONENT_FUNCTION_NAME_PREFIX)) return false + + try { + getComponentIndex(name) + } + catch (e: NumberFormatException) { + return false + } + + return true +} + +public fun getComponentIndex(componentName: Name): Int = + componentName.asString().substring(COMPONENT_FUNCTION_NAME_PREFIX.length).toInt() + +public fun createComponentName(index: Int): Name = + Name.identifier(COMPONENT_FUNCTION_NAME_PREFIX + index) \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index af8593d4e53..641548b040c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant; +import org.jetbrains.jet.lang.resolve.dataClassUtils.DataClassUtilsPackage; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -63,7 +64,6 @@ import static org.jetbrains.jet.lexer.JetTokens.VARARG_KEYWORD; public class DescriptorResolver { public static final Name COPY_METHOD_NAME = Name.identifier("copy"); - public static final String COMPONENT_FUNCTION_NAME_PREFIX = "component"; private static final Set MODIFIERS_ILLEGAL_ON_PARAMETERS; static { MODIFIERS_ILLEGAL_ON_PARAMETERS = Sets.newHashSet(); @@ -382,13 +382,13 @@ public class DescriptorResolver { @NotNull ClassDescriptor classDescriptor, @NotNull BindingTrace trace ) { - String functionName = COMPONENT_FUNCTION_NAME_PREFIX + parameterIndex; + Name functionName = DataClassUtilsPackage.createComponentName(parameterIndex); JetType returnType = property.getType(); SimpleFunctionDescriptorImpl functionDescriptor = SimpleFunctionDescriptorImpl.create( classDescriptor, Annotations.EMPTY, - Name.identifier(functionName), + functionName, CallableMemberDescriptor.Kind.SYNTHESIZED, parameter.getSource() ); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index 032eb8f8d6e..6d0ef7b3869 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -35,6 +35,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; +import org.jetbrains.jet.lang.resolve.dataClassUtils.DataClassUtilsPackage; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.*; @@ -598,8 +599,7 @@ public class OverrideResolver { private void checkOverrideForMember(@NotNull final CallableMemberDescriptor declared) { if (declared.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) { - // TODO: this should be replaced soon by a framework of synthesized member generation tools - if (declared.getName().asString().startsWith(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX)) { + if (DataClassUtilsPackage.isComponentLike(declared.getName())) { checkOverrideForComponentFunction(declared); } return; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.java index 601de91be18..ddf81b83139 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.java @@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.dataClassUtils.DataClassUtilsPackage; import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo; import org.jetbrains.jet.lang.resolve.lazy.declarations.ClassMemberDeclarationProvider; @@ -174,10 +175,9 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope functions = getFunctions(componentName); if (functions.isEmpty()) break; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index 9bb06e8bc54..4f96f6067d9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -43,6 +43,7 @@ import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; +import org.jetbrains.jet.lang.resolve.dataClassUtils.DataClassUtilsPackage; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; @@ -336,7 +337,7 @@ public class ExpressionTypingUtils { ) { int componentIndex = 1; for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) { - Name componentName = Name.identifier(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX + componentIndex); + Name componentName = DataClassUtilsPackage.createComponentName(componentIndex); componentIndex++; JetType expectedType = getExpectedTypeForComponent(context, entry); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/name/NameUtil.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/name/NameUtil.kt deleted file mode 100644 index 47f2e1518b8..00000000000 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/name/NameUtil.kt +++ /dev/null @@ -1,8 +0,0 @@ -package org.jetbrains.jet.lang.resolve.name - -import java.util.regex.Pattern - -public val COMPONENT_FUNCTION_PATTERN: Pattern = Pattern.compile("^component(\\d+)$") - -public fun String.isComponentFunctionName(): Boolean = COMPONENT_FUNCTION_PATTERN.matcher(this).matches() -public fun Name.isComponentFunctionName(): Boolean = asString().isComponentFunctionName() \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/libraries/DecompiledTextFactory.kt b/idea/idea-analysis/src/org/jetbrains/jet/plugin/libraries/DecompiledTextFactory.kt index 14438bbf958..811f322bbc8 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/libraries/DecompiledTextFactory.kt +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/libraries/DecompiledTextFactory.kt @@ -29,7 +29,7 @@ import java.util.* import org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumEntry import org.jetbrains.jet.lang.resolve.DescriptorUtils.isSyntheticClassObject import org.jetbrains.jet.lang.types.error.MissingDependencyErrorClass -import org.jetbrains.jet.lang.resolve.name.isComponentFunctionName +import org.jetbrains.jet.lang.resolve.dataClassUtils.isComponentLike public fun buildDecompiledText( classFile: VirtualFile, @@ -128,7 +128,7 @@ private fun buildDecompiledText(packageFqName: FqName, descriptors: List @NotNull public static JetMultiDeclarationEntry getMultiDeclarationEntryThatTypeMismatchComponentFunction(Diagnostic diagnostic) { - String componentName = COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.cast(diagnostic).getA().asString(); - int componentIndex = Integer.valueOf(componentName.substring(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX.length())); + Name componentName = COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.cast(diagnostic).getA(); + int componentIndex = DataClassUtilsPackage.getComponentIndex(componentName); JetMultiDeclaration multiDeclaration = QuickFixUtil.getParentElementOfType(diagnostic, JetMultiDeclaration.class); assert multiDeclaration != null : "COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH reported on expression that is not within any multi declaration"; return multiDeclaration.getEntries().get(componentIndex - 1); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/CreateFunctionFromUsageFix.kt b/idea/src/org/jetbrains/jet/plugin/quickfix/CreateFunctionFromUsageFix.kt index e299503ca40..4e3ea9b1708 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/CreateFunctionFromUsageFix.kt +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/CreateFunctionFromUsageFix.kt @@ -70,7 +70,8 @@ import org.jetbrains.jet.plugin.caches.resolve.getAnalysisResults import org.jetbrains.jet.plugin.caches.resolve.getBindingContext import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils -import org.jetbrains.jet.lang.resolve.name.COMPONENT_FUNCTION_PATTERN +import org.jetbrains.jet.lang.resolve.dataClassUtils.isComponentLike +import org.jetbrains.jet.lang.resolve.dataClassUtils.getComponentIndex private val TYPE_PARAMETER_LIST_VARIABLE_NAME = "typeParameterList" private val TEMPLATE_FROM_USAGE_FUNCTION_BODY = "New Kotlin Function Body.kt" @@ -964,10 +965,9 @@ public class CreateFunctionFromUsageFix internal ( override fun createAction(diagnostic: Diagnostic): IntentionAction? { val diagnosticWithParameters = Errors.COMPONENT_FUNCTION_MISSING.cast(diagnostic) val name = diagnosticWithParameters.getA() - val componentNumberMatcher = COMPONENT_FUNCTION_PATTERN.matcher(name.getIdentifier()) - if (!componentNumberMatcher.matches()) return null - val componentNumberString = componentNumberMatcher.group(1)!! - val componentNumber = Integer.decode(componentNumberString)!! - 1 + if (!isComponentLike(name)) return null + + val componentNumber = getComponentIndex(name) - 1 var multiDeclaration = QuickFixUtil.getParentElementOfType(diagnostic, javaClass()) val ownerType = if (multiDeclaration == null) { diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.kt b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.kt index 07cade2d14d..20d2a5a5a48 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.kt +++ b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.kt @@ -31,12 +31,12 @@ import org.jetbrains.jet.plugin.refactoring.getKotlinFqName import org.jetbrains.jet.lang.types.expressions.OperatorConventions import org.jetbrains.jet.lexer.JetToken import org.jetbrains.jet.plugin.intentions.OperatorToFunctionIntention -import org.jetbrains.jet.lang.psi.psiUtil.getParentByType import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache import org.jetbrains.jet.lang.resolve.BindingContext -import org.jetbrains.jet.lang.resolve.DescriptorResolver import com.intellij.util.IncorrectOperationException import org.jetbrains.jet.lang.psi.psiUtil.getParentByTypeAndBranch +import org.jetbrains.jet.lang.resolve.name.Name +import org.jetbrains.jet.lang.resolve.dataClassUtils.isComponentLike public class JetSimpleNameReference( jetSimpleNameExpression: JetSimpleNameExpression @@ -58,8 +58,11 @@ public class JetSimpleNameReference( if (newElementName == null) return expression; // Do not rename if the reference corresponds to synthesized component function - if ((expression.getText() ?: "").startsWith(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX) && resolve() is JetParameter) { - return expression + val expressionText = expression.getText() + if (expressionText != null && Name.isValidIdentifier(expressionText)) { + if (isComponentLike(Name.identifier(expressionText)) && resolve() is JetParameter) { + return expression + } } val psiFactory = JetPsiFactory(expression) diff --git a/idea/src/org/jetbrains/jet/plugin/search/usagesSearch/conventions.kt b/idea/src/org/jetbrains/jet/plugin/search/usagesSearch/conventions.kt index 07908893172..3e9123115e9 100644 --- a/idea/src/org/jetbrains/jet/plugin/search/usagesSearch/conventions.kt +++ b/idea/src/org/jetbrains/jet/plugin/search/usagesSearch/conventions.kt @@ -22,7 +22,7 @@ import org.jetbrains.jet.lang.types.expressions.OperatorConventions.* import com.google.common.collect.ImmutableSet import org.jetbrains.jet.lexer.JetTokens import org.jetbrains.jet.lexer.JetSingleValueToken -import java.util.regex.Pattern +import org.jetbrains.jet.lang.resolve.dataClassUtils.isComponentLike public val ALL_SEARCHABLE_OPERATIONS: ImmutableSet = ImmutableSet .builder() @@ -48,8 +48,6 @@ public val INVOKE_OPERATION_NAME: Name = Name.identifier("invoke") public val ITERATOR_OPERATION_NAME: Name = Name.identifier("iterator") -public val COMPONENT_OPERATION_PATTERN: Pattern = Pattern.compile("component\\d+") - public val IN_OPERATIONS_TO_SEARCH: ImmutableSet = ImmutableSet.of(JetTokens.IN_KEYWORD) public val COMPARISON_OPERATIONS_TO_SEARCH: ImmutableSet = ImmutableSet.of(JetTokens.LT, JetTokens.GT) @@ -65,7 +63,7 @@ public fun Name.getOperationSymbolsToSearch(): Set { in INDEXING_OPERATION_NAMES -> return ImmutableSet.of(JetTokens.LBRACKET) } - if (COMPONENT_OPERATION_PATTERN.matcher(asString()).matches()) return ImmutableSet.of(JetTokens.LPAR) + if (isComponentLike(this)) return ImmutableSet.of(JetTokens.LPAR) val unaryOp = UNARY_OPERATION_NAMES.inverse()[this] if (unaryOp != null) return ImmutableSet.of(unaryOp) diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java b/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java index 1ca9c683545..d7cb186029a 100644 --- a/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java @@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.Visibilities; import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.dataClassUtils.DataClassUtilsPackage; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.plugin.KotlinCodeInsightTestCase; import org.jetbrains.jet.plugin.PluginTestCaseBase; @@ -87,7 +88,7 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase { getChangeInfo(); } catch (CommonRefactoringUtil.RefactoringErrorHintException e) { - assertEquals(JetRefactoringBundle.message("cannot.refactor.synthesized.function", "component1"), e.getMessage()); + assertEquals(JetRefactoringBundle.message("cannot.refactor.synthesized.function", DataClassUtilsPackage.createComponentName(1).asString()), e.getMessage()); return; } fail();