diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.kt index 75e2c51c0ee..6d8f28f32a0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.kt @@ -16,30 +16,23 @@ package org.jetbrains.jet.lang.diagnostics - -import com.google.common.collect.ImmutableList -import com.google.common.collect.Lists -import com.intellij.lang.ASTNode import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import com.intellij.psi.PsiNameIdentifierOwner import com.intellij.psi.tree.TokenSet -import kotlin.Function1 import org.jetbrains.jet.JetNodeTypes import org.jetbrains.jet.lang.psi.* import org.jetbrains.jet.lexer.JetKeywordToken -import org.jetbrains.jet.lexer.JetModifierKeywordToken import org.jetbrains.jet.lexer.JetTokens -import java.util.Arrays -import java.util.Collections - -public class PositioningStrategies private() { +import kotlin.platform.platformStatic +import org.jetbrains.kotlin.util.sure +public object PositioningStrategies { private open class DeclarationHeader : PositioningStrategy() { override fun isValid(element: T): Boolean { - if (element is JetNamedDeclaration && !(element is JetObjectDeclaration)) { - if ((element as JetNamedDeclaration).getNameIdentifier() == null) { + if (element is JetNamedDeclaration && element !is JetObjectDeclaration) { + if (element.getNameIdentifier() == null) { return false } } @@ -47,12 +40,11 @@ public class PositioningStrategies private() { } } - class object { - - public val DEFAULT: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: PsiElement): List { - if (element is JetObjectLiteralExpression) { - val objectDeclaration = (element as JetObjectLiteralExpression).getObjectDeclaration() + public val DEFAULT: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: PsiElement): List { + when (element) { + is JetObjectLiteralExpression -> { + val objectDeclaration = element.getObjectDeclaration() val objectKeyword = objectDeclaration.getObjectKeyword() val delegationSpecifierList = objectDeclaration.getDelegationSpecifierList() if (delegationSpecifierList == null) { @@ -60,425 +52,319 @@ public class PositioningStrategies private() { } return markRange(objectKeyword, delegationSpecifierList) } - else if (element is JetClassObject) { - val classObject = element as JetClassObject - val classKeyword = classObject.getClassKeyword() - val objectKeyword = classObject.getObjectDeclaration().getObjectKeyword() + is JetClassObject -> { + val classKeyword = element.getClassKeyword() + val objectKeyword = element.getObjectDeclaration().getObjectKeyword() return markRange(classKeyword, objectKeyword) } - else { + else -> { return super.mark(element) } } } + } - public val DECLARATION_RETURN_TYPE: PositioningStrategy = object : PositioningStrategy() { - override fun mark(declaration: JetDeclaration): List { - return markElement(getElementToMark(declaration)) - } - - override fun isValid(declaration: JetDeclaration): Boolean { - return !hasSyntaxErrors(getElementToMark(declaration)) - } - - private fun getElementToMark(declaration: JetDeclaration): PsiElement { - var returnTypeRef: JetTypeReference? = null - var nameIdentifierOrPlaceholder: PsiElement? = null - if (declaration is JetNamedFunction) { - val function = declaration as JetNamedFunction - returnTypeRef = function.getTypeReference() - nameIdentifierOrPlaceholder = function.getNameIdentifier() - } - else if (declaration is JetProperty) { - val property = declaration as JetProperty - returnTypeRef = property.getTypeReference() - nameIdentifierOrPlaceholder = property.getNameIdentifier() - } - else if (declaration is JetPropertyAccessor) { - val accessor = declaration as JetPropertyAccessor - returnTypeRef = accessor.getReturnTypeReference() - nameIdentifierOrPlaceholder = accessor.getNamePlaceholder() - } - - if (returnTypeRef != null) return returnTypeRef - if (nameIdentifierOrPlaceholder != null) return nameIdentifierOrPlaceholder - return declaration - } + public val DECLARATION_RETURN_TYPE: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetDeclaration): List { + return markElement(getElementToMark(element)) } - public val DECLARATION_NAME: PositioningStrategy = object : DeclarationHeader() { - override fun mark(element: JetNamedDeclaration): List { - val nameIdentifier = element.getNameIdentifier() - if (nameIdentifier != null) { - if (element is JetClassOrObject) { - var startNode: ASTNode? = null - if (element.hasModifier(JetTokens.ENUM_KEYWORD)) { - //noinspection ConstantConditions - startNode = element.getModifierList()!!.getModifier(JetTokens.ENUM_KEYWORD)!!.getNode() - } - if (startNode == null) { - startNode = element.getNode().findChildByType(TokenSet.create(JetTokens.CLASS_KEYWORD, JetTokens.OBJECT_KEYWORD)) - } - if (startNode == null) { - startNode = element.getNode() - } - return markRange(startNode!!.getPsi(), nameIdentifier) - } - return markElement(nameIdentifier) - } - if (element is JetObjectDeclaration) { - val objectKeyword = (element as JetObjectDeclaration).getObjectKeyword() - val parent = element.getParent() - if (parent is JetClassObject) { - val classKeyword = (parent as JetClassObject).getClassKeyword() - val start = if (classKeyword == null) objectKeyword else classKeyword - return markRange(start, objectKeyword) - } - return markElement(objectKeyword) - } - return super.mark(element) - } + override fun isValid(element: JetDeclaration): Boolean { + return !hasSyntaxErrors(getElementToMark(element)) } - public val DECLARATION_SIGNATURE: PositioningStrategy = object : DeclarationHeader() { - override fun mark(element: JetDeclaration): List { - if (element is JetNamedFunction) { - val function = element as JetNamedFunction - val endOfSignatureElement: PsiElement - val valueParameterList = function.getValueParameterList() - val returnTypeRef = function.getTypeReference() - val nameIdentifier = function.getNameIdentifier() - if (returnTypeRef != null) { - endOfSignatureElement = returnTypeRef - } - else if (valueParameterList != null) { - endOfSignatureElement = valueParameterList - } - else if (nameIdentifier != null) { - endOfSignatureElement = nameIdentifier - } - else { - endOfSignatureElement = function - } - return markRange(function, endOfSignatureElement) + private fun getElementToMark(declaration: JetDeclaration): PsiElement { + val (returnTypeRef, nameIdentifierOrPlaceholder) = when (declaration) { + is JetCallableDeclaration -> Pair(declaration.getTypeReference(), declaration.getNameIdentifier()) + is JetPropertyAccessor -> Pair(declaration.getReturnTypeReference(), declaration.getNamePlaceholder()) + else -> Pair(null, null) + } + + if (returnTypeRef != null) return returnTypeRef + if (nameIdentifierOrPlaceholder != null) return nameIdentifierOrPlaceholder + return declaration + } + } + + public val DECLARATION_NAME: PositioningStrategy = object : DeclarationHeader() { + override fun mark(element: JetNamedDeclaration): List { + val nameIdentifier = element.getNameIdentifier() + if (nameIdentifier != null) { + if (element is JetClassOrObject) { + val startElement = + element.getModifierList()?.getModifier(JetTokens.ENUM_KEYWORD) + ?: element.getNode().findChildByType(TokenSet.create(JetTokens.CLASS_KEYWORD, JetTokens.OBJECT_KEYWORD))?.getPsi() + ?: element + + return markRange(startElement, nameIdentifier) } - else if (element is JetProperty) { - val property = element as JetProperty - val endOfSignatureElement: PsiElement - val propertyTypeRef = property.getTypeReference() - val nameIdentifier = property.getNameIdentifier() - if (propertyTypeRef != null) { - endOfSignatureElement = propertyTypeRef - } - else if (nameIdentifier != null) { - endOfSignatureElement = nameIdentifier - } - else { - endOfSignatureElement = property - } - return markRange(property, endOfSignatureElement) + return markElement(nameIdentifier) + } + if (element is JetObjectDeclaration) { + val objectKeyword = element.getObjectKeyword() + val parent = element.getParent() + if (parent is JetClassObject) { + val classKeyword = parent.getClassKeyword() + val start = classKeyword ?: objectKeyword + return markRange(start, objectKeyword) } - else if (element is JetPropertyAccessor) { - val accessor = element as JetPropertyAccessor - var endOfSignatureElement: PsiElement? = accessor.getReturnTypeReference() - if (endOfSignatureElement == null) { - val rpar = accessor.getRightParenthesis() - endOfSignatureElement = if (rpar == null) null else rpar.getPsi() - } - if (endOfSignatureElement == null) { - endOfSignatureElement = accessor.getNamePlaceholder() - } - return markRange(accessor, endOfSignatureElement) + return markElement(objectKeyword) + } + return super.mark(element) + } + } + + public val DECLARATION_SIGNATURE: PositioningStrategy = object : DeclarationHeader() { + override fun mark(element: JetDeclaration): List { + when (element) { + is JetNamedFunction -> { + val endOfSignatureElement = + element.getTypeReference() + ?: element.getValueParameterList() + ?: element.getNameIdentifier() + ?: element + + return markRange(element, endOfSignatureElement) } - else if (element is JetClass) { - val nameAsDeclaration = (element as JetClass).getNameIdentifier() - if (nameAsDeclaration == null) { - return markElement(element) - } - val primaryConstructorParameterList = (element as JetClass).getPrimaryConstructorParameterList() - if (primaryConstructorParameterList == null) { - return markElement(nameAsDeclaration) - } + is JetProperty -> { + val endOfSignatureElement = element.getTypeReference() ?: element.getNameIdentifier() ?: element + return markRange(element, endOfSignatureElement) + } + is JetPropertyAccessor -> { + val endOfSignatureElement = + element.getReturnTypeReference() + ?: element.getRightParenthesis()?.getPsi() + ?: element.getNamePlaceholder() + + return markRange(element, endOfSignatureElement) + } + is JetClass -> { + val nameAsDeclaration = element.getNameIdentifier() ?: return markElement(element) + val primaryConstructorParameterList = element.getPrimaryConstructorParameterList() ?: return markElement(nameAsDeclaration) return markRange(nameAsDeclaration, primaryConstructorParameterList) } - else if (element is JetObjectDeclaration) { - return DECLARATION_NAME.mark(element as JetObjectDeclaration) + is JetObjectDeclaration -> { + return DECLARATION_NAME.mark(element) } - return super.mark(element) } + return super.mark(element) + } + } + + public val DECLARATION_SIGNATURE_OR_DEFAULT: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: PsiElement): List { + return if (element is JetDeclaration) + DECLARATION_SIGNATURE.mark(element) + else + DEFAULT.mark(element) } - public val DECLARATION_SIGNATURE_OR_DEFAULT: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: PsiElement): List { - if (element is JetDeclaration) { - return DECLARATION_SIGNATURE.mark(element as JetDeclaration) - } - return DEFAULT.mark(element) - } - - override fun isValid(element: PsiElement): Boolean { - if (element is JetDeclaration) { - return DECLARATION_SIGNATURE.isValid(element as JetDeclaration) - } - return DEFAULT.isValid(element) - } + override fun isValid(element: PsiElement): Boolean { + return if (element is JetDeclaration) + DECLARATION_SIGNATURE.isValid(element) + else + DEFAULT.isValid(element) } + } - public val ABSTRACT_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.ABSTRACT_KEYWORD) + public val ABSTRACT_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.ABSTRACT_KEYWORD) - public val OVERRIDE_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.OVERRIDE_KEYWORD) + public val OVERRIDE_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.OVERRIDE_KEYWORD) - public val FINAL_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.FINAL_KEYWORD) + public val FINAL_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.FINAL_KEYWORD) - public val VARIANCE_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.IN_KEYWORD, JetTokens.OUT_KEYWORD) - public val FOR_REDECLARATION: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: PsiElement): List { - if (element is JetNamedDeclaration) { - val nameIdentifier = (element as JetNamedDeclaration).getNameIdentifier() - if (nameIdentifier != null) { - return markElement(nameIdentifier) - } - } - else if (element is JetFile) { - val file = element as JetFile - val nameIdentifier = file.getPackageDirective()!!.getNameIdentifier() - if (nameIdentifier != null) { - return markElement(nameIdentifier) - } - } - return markElement(element) + public val VARIANCE_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.IN_KEYWORD, JetTokens.OUT_KEYWORD) + + public val FOR_REDECLARATION: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: PsiElement): List { + val nameIdentifier = when (element) { + is JetNamedDeclaration -> element.getNameIdentifier() + is JetFile -> element.getPackageDirective()!!.getNameIdentifier() + else -> null } - } - public val FOR_UNRESOLVED_REFERENCE: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: JetReferenceExpression): List { - if (element is JetArrayAccessExpression) { - val ranges = (element as JetArrayAccessExpression).getBracketRanges() - if (!ranges.isEmpty()) { - return ranges - } - } - return listOf(element.getTextRange()) - } - } - public fun modifierSetPosition(vararg tokens: JetKeywordToken): PositioningStrategy { - return object : PositioningStrategy() { - override fun mark(modifierListOwner: JetModifierListOwner): List { - val modifierList = modifierListOwner.getModifierList() - assert(modifierList != null, "No modifier list, but modifier has been found by the analyzer") - - for (token in tokens) { - val node = modifierList!!.getModifierNode(token) - if (node != null) { - return markNode(node) - } - } - throw IllegalStateException("None of the modifiers is found: " + Arrays.asList(*tokens)) + return markElement(nameIdentifier ?: element) + } + } + public val FOR_UNRESOLVED_REFERENCE: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetReferenceExpression): List { + if (element is JetArrayAccessExpression) { + val ranges = element.getBracketRanges() + if (!ranges.isEmpty()) { + return ranges } } + return listOf(element.getTextRange()) } + } - public val ARRAY_ACCESS: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: JetArrayAccessExpression): List { - return markElement(element.getIndicesNode()) - } - } - - public val VISIBILITY_MODIFIER: PositioningStrategy = object : PositioningStrategy() { + platformStatic + public fun modifierSetPosition(vararg tokens: JetKeywordToken): PositioningStrategy { + return object : PositioningStrategy() { override fun mark(element: JetModifierListOwner): List { - val visibilityTokens = Lists.newArrayList(JetTokens.PRIVATE_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PUBLIC_KEYWORD, JetTokens.INTERNAL_KEYWORD) - val result = Lists.newArrayList() - for (token in visibilityTokens) { - if (element.hasModifier(token)) { - //noinspection ConstantConditions - result.add(element.getModifierList()!!.getModifierNode(token)!!.getTextRange()) + val modifierList = element.getModifierList().sure("No modifier list, but modifier has been found by the analyzer") + + for (token in tokens) { + val node = modifierList.getModifierNode(token) + if (node != null) { + return markNode(node) } } + throw IllegalStateException("None of the modifiers is found: " + listOf(*tokens)) + } + } + } - if (!result.isEmpty()) return result + public val ARRAY_ACCESS: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetArrayAccessExpression): List { + return markElement(element.getIndicesNode()) + } + } - // Try to resolve situation when there's no visibility modifiers written before element + public val VISIBILITY_MODIFIER: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetModifierListOwner): List { + val visibilityTokens = listOf(JetTokens.PRIVATE_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PUBLIC_KEYWORD, JetTokens.INTERNAL_KEYWORD) + val modifierList = element.getModifierList() - if (element is PsiNameIdentifierOwner) { - val nameIdentifier = (element as PsiNameIdentifierOwner).getNameIdentifier() - if (nameIdentifier != null) { - return ImmutableList.of(nameIdentifier.getTextRange()) - } + val result = visibilityTokens.map { modifierList?.getModifierNode(it)?.getTextRange() }.filterNotNull() + if (!result.isEmpty()) return result + + // Try to resolve situation when there's no visibility modifiers written before element + if (element is PsiNameIdentifierOwner) { + val nameIdentifier = element.getNameIdentifier() + if (nameIdentifier != null) { + return markElement(nameIdentifier) } + } - if (element is JetObjectDeclaration) { - return ImmutableList.of((element as JetObjectDeclaration).getObjectKeyword().getTextRange()) + val elementToMark = when (element) { + is JetObjectDeclaration -> element.getObjectKeyword() + is JetPropertyAccessor -> element.getNamePlaceholder() + is JetClassInitializer -> element + is JetClassObject -> element.getObjectDeclaration().getObjectKeyword() + else -> throw IllegalArgumentException( + "Can't find text range for element '${element.javaClass.getCanonicalName()}' with the text '${element.getText()}'") + } + return markElement(elementToMark) + } + } + + public val VARIANCE_IN_PROJECTION: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetTypeProjection): List { + return markNode(element.getProjectionNode()) + } + } + + public val PARAMETER_DEFAULT_VALUE: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetParameter): List { + return markNode(element.getDefaultValue()!!.getNode()) + } + } + + public val CALL_ELEMENT: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: PsiElement): List { + return markElement((element as? JetCallElement)?.getCalleeExpression() ?: element) + } + } + + public val DECLARATION_WITH_BODY: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetDeclarationWithBody): List { + val lastBracketRange = (element.getBodyExpression() as? JetBlockExpression)?.getLastBracketRange() + return if (lastBracketRange != null) + markRange(lastBracketRange) + else + markElement(element) + } + + override fun isValid(element: JetDeclarationWithBody): Boolean { + return super.isValid(element) && (element.getBodyExpression() as? JetBlockExpression)?.getLastBracketRange() != null + } + } + + public val VAL_OR_VAR_NODE: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetProperty): List { + return markNode(element.getValOrVarNode()) + } + } + + public val ELSE_ENTRY: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetWhenEntry): List { + return markElement(element.getElseKeywordElement()!!) + } + } + + public val WHEN_EXPRESSION: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetWhenExpression): List { + return markElement(element.getWhenKeywordElement()) + } + } + + public val WHEN_CONDITION_IN_RANGE: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetWhenConditionInRange): List { + return markElement(element.getOperationReference()) + } + } + + public val NULLABLE_TYPE: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetNullableType): List { + return markNode(element.getQuestionMarkNode()) + } + } + + public val CALL_EXPRESSION: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: PsiElement): List { + if (element is JetCallExpression) { + return markRange(element, element.getTypeArgumentList() ?: element.getCalleeExpression() ?: element) + } + return markElement(element) + } + } + + public val VALUE_ARGUMENTS: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetElement): List { + return markElement((element as? JetValueArgumentList)?.getRightParenthesis() ?: element) + } + } + + public val FUNCTION_LITERAL_PARAMETERS: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetFunctionLiteral): List { + val valueParameterList = element.getValueParameterList() + if (valueParameterList != null) { + return markElement(valueParameterList) + } + return markNode(element.getLBrace().getNode()) + } + } + + public val CUT_CHAR_QUOTES: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetElement): List { + if (element is JetConstantExpression) { + if (element.getNode().getElementType() == JetNodeTypes.CHARACTER_CONSTANT) { + val elementTextRange = element.getTextRange() + return listOf(TextRange.create(elementTextRange.getStartOffset() + 1, elementTextRange.getEndOffset() - 1)) } + } + return markElement(element) + } + } - if (element is JetPropertyAccessor) { - return ImmutableList.of((element as JetPropertyAccessor).getNamePlaceholder().getTextRange()) + public val LONG_LITERAL_SUFFIX: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetElement): List { + if (element is JetConstantExpression) { + if (element.getNode().getElementType() == JetNodeTypes.INTEGER_CONSTANT) { + val endOffset = element.getTextRange().getEndOffset() + return listOf(TextRange.create(endOffset - 1, endOffset)) } - - if (element is JetClassInitializer) { - return ImmutableList.of(element.getTextRange()) - } - - if (element is JetClassObject) { - val objectDeclaration = (element as JetClassObject).getObjectDeclaration() - return ImmutableList.of(objectDeclaration.getObjectKeyword().getTextRange()) - } - - throw IllegalArgumentException(String.format("Can't find text range for element '%s' with the text '%s'", element.javaClass.getCanonicalName(), element.getText())) } + return markElement(element) } + } - public val VARIANCE_IN_PROJECTION: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: JetTypeProjection): List { - return markNode(element.getProjectionNode()) - } - } - - public val PARAMETER_DEFAULT_VALUE: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: JetParameter): List { - return markNode(element.getDefaultValue()!!.getNode()) - } - } - - public val CALL_ELEMENT: PositioningStrategy = object : PositioningStrategy() { - override fun mark(callElement: PsiElement): List { - if (callElement is JetCallElement) { - val calleeExpression = (callElement as JetCallElement).getCalleeExpression() - if (calleeExpression != null) { - return markElement(calleeExpression) - } - } - return markElement(callElement) - } - } - - public val DECLARATION_WITH_BODY: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: JetDeclarationWithBody): List { - val bodyExpression = element.getBodyExpression() - if ((bodyExpression is JetBlockExpression)) { - val lastBracketRange = (bodyExpression as JetBlockExpression).getLastBracketRange() - if (lastBracketRange != null) { - return markRange(lastBracketRange) - } - } - return markElement(element) - } - - override fun isValid(element: JetDeclarationWithBody): Boolean { - if (!super.isValid(element)) return false - - val bodyExpression = element.getBodyExpression() - if (!(bodyExpression is JetBlockExpression)) return false - if ((bodyExpression as JetBlockExpression).getLastBracketRange() == null) return false - return true - } - } - - public val VAL_OR_VAR_NODE: PositioningStrategy = object : PositioningStrategy() { - override fun mark(property: JetProperty): List { - return markNode(property.getValOrVarNode()) - } - } - - public val ELSE_ENTRY: PositioningStrategy = object : PositioningStrategy() { - override fun mark(entry: JetWhenEntry): List { - val elseKeywordElement = entry.getElseKeywordElement() - assert(elseKeywordElement != null) - return markElement(elseKeywordElement) - } - } - - public val WHEN_EXPRESSION: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: JetWhenExpression): List { - return markElement(element.getWhenKeywordElement()) - } - } - - public val WHEN_CONDITION_IN_RANGE: PositioningStrategy = object : PositioningStrategy() { - override fun mark(condition: JetWhenConditionInRange): List { - return markElement(condition.getOperationReference()) - } - } - - public val NULLABLE_TYPE: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: JetNullableType): List { - return markNode(element.getQuestionMarkNode()) - } - } - - public val CALL_EXPRESSION: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: PsiElement): List { - if (element is JetCallExpression) { - val callExpression = element as JetCallExpression - val endElement: PsiElement - val typeArgumentList = callExpression.getTypeArgumentList() - val calleeExpression = callExpression.getCalleeExpression() - if (typeArgumentList != null) { - endElement = typeArgumentList - } - else if (calleeExpression != null) { - endElement = calleeExpression - } - else { - endElement = element - } - return markRange(element, endElement) - } - return super.mark(element) - } - } - - public val VALUE_ARGUMENTS: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: JetElement): List { - if (element is JetValueArgumentList) { - val rightParenthesis = (element as JetValueArgumentList).getRightParenthesis() - if (rightParenthesis != null) { - return markElement(rightParenthesis) - } - - } - return super.mark(element) - } - } - - public val FUNCTION_LITERAL_PARAMETERS: PositioningStrategy = object : PositioningStrategy() { - override fun mark(functionLiteral: JetFunctionLiteral): List { - val valueParameterList = functionLiteral.getValueParameterList() - if (valueParameterList != null) { - return markElement(valueParameterList) - } - return markNode(functionLiteral.getLBrace().getNode()) - } - } - - public val CUT_CHAR_QUOTES: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: JetElement): List { - if (element is JetConstantExpression) { - if (element.getNode().getElementType() == JetNodeTypes.CHARACTER_CONSTANT) { - val elementTextRange = element.getTextRange() - return listOf(TextRange.create(elementTextRange.getStartOffset() + 1, elementTextRange.getEndOffset() - 1)) - } - } - return super.mark(element) - } - } - - public val LONG_LITERAL_SUFFIX: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: JetElement): List { - if (element is JetConstantExpression) { - if (element.getNode().getElementType() == JetNodeTypes.INTEGER_CONSTANT) { - val endOffset = element.getTextRange().getEndOffset() - return listOf(TextRange.create(endOffset - 1, endOffset)) - } - } - return super.mark(element) - } - } - - public fun markTextRangesFromDiagnostic(getTextRanges: Function1>): PositioningStrategy { - return object : PositioningStrategy() { - override fun markDiagnostic(diagnostic: ParametrizedDiagnostic): List { - return getTextRanges.invoke(diagnostic) - } + [platformStatic] + public fun markTextRangesFromDiagnostic(getTextRanges: (Diagnostic) -> List): PositioningStrategy { + return object : PositioningStrategy() { + override fun markDiagnostic(diagnostic: ParametrizedDiagnostic): List { + return getTextRanges(diagnostic) } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.kt b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.kt index 28f4d4afca0..acce129f19a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.kt @@ -23,8 +23,6 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiErrorElement import com.intellij.psi.PsiWhiteSpace -import java.util.Collections - public open class PositioningStrategy { public open fun markDiagnostic(diagnostic: ParametrizedDiagnostic): List { return mark(diagnostic.getPsiElement()) @@ -37,58 +35,54 @@ public open class PositioningStrategy { public open fun isValid(element: E): Boolean { return !hasSyntaxErrors(element) } +} - class object { +fun markElement(element: PsiElement): List { + return listOf(TextRange(getStartOffset(element), getEndOffset(element))) +} - protected fun markElement(element: PsiElement): List { - return listOf(TextRange(getStartOffset(element), getEndOffset(element))) +fun markNode(node: ASTNode): List { + return markElement(node.getPsi()) +} + +fun markRange(range: TextRange): List { + return listOf(range) +} + +fun markRange(from: PsiElement, to: PsiElement): List { + return markRange(TextRange(getStartOffset(from), getEndOffset(to))) +} + +private fun getStartOffset(element: PsiElement): Int { + var child = element.getFirstChild() + if (child != null) { + while (child is PsiComment || child is PsiWhiteSpace) { + child = child!!.getNextSibling() } - - protected fun markNode(node: ASTNode): List { - return markElement(node.getPsi()) - } - - protected fun markRange(range: TextRange): List { - return listOf(range) - } - - protected fun markRange(from: PsiElement, to: PsiElement): List { - return markRange(TextRange(getStartOffset(from), getEndOffset(to))) - } - - private fun getStartOffset(element: PsiElement): Int { - var child: PsiElement? = element.getFirstChild() - if (child != null) { - while (child is PsiComment || child is PsiWhiteSpace) { - child = child!!.getNextSibling() - } - if (child != null) { - return getStartOffset(child) - } - } - return element.getTextRange().getStartOffset() - } - - private fun getEndOffset(element: PsiElement): Int { - var child: PsiElement? = element.getLastChild() - if (child != null) { - while (child is PsiComment || child is PsiWhiteSpace) { - child = child!!.getPrevSibling() - } - if (child != null) { - return getEndOffset(child) - } - } - return element.getTextRange().getEndOffset() - } - - protected fun hasSyntaxErrors(psiElement: PsiElement): Boolean { - if (psiElement is PsiErrorElement) return true - - val children = psiElement.getChildren() - if (children.size > 0 && hasSyntaxErrors(children[children.size - 1])) return true - - return false + if (child != null) { + return getStartOffset(child!!) } } + return element.getTextRange().getStartOffset() } + +private fun getEndOffset(element: PsiElement): Int { + var child = element.getLastChild() + if (child != null) { + while (child is PsiComment || child is PsiWhiteSpace) { + child = child!!.getPrevSibling() + } + if (child != null) { + return getEndOffset(child!!) + } + } + return element.getTextRange().getEndOffset() +} + +fun hasSyntaxErrors(psiElement: PsiElement): Boolean { + if (psiElement is PsiErrorElement) return true + + val children = psiElement.getChildren() + return children.isNotEmpty() && hasSyntaxErrors(children.last()) +} +