Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.diagnostics
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.utils.sure
object PositioningStrategies {
private open class DeclarationHeader : PositioningStrategy() {
override fun isValid(element: T): Boolean {
if (element is KtNamedDeclaration &&
element !is KtObjectDeclaration &&
element !is KtSecondaryConstructor &&
element !is KtFunction
) {
if (element.nameIdentifier == null) {
return false
}
}
return super.isValid(element)
}
}
@JvmField val DEFAULT: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: PsiElement): List {
when (element) {
is KtObjectLiteralExpression -> {
val objectDeclaration = element.objectDeclaration
val objectKeyword = objectDeclaration.getObjectKeyword()
val delegationSpecifierList = objectDeclaration.getSuperTypeList()
if (delegationSpecifierList == null) {
return markElement(objectKeyword)
}
return markRange(objectKeyword, delegationSpecifierList)
}
is KtObjectDeclaration -> {
return markRange(
element.getObjectKeyword(),
element.getNameIdentifier() ?: element.getObjectKeyword()
)
}
is KtConstructorDelegationCall -> {
return SECONDARY_CONSTRUCTOR_DELEGATION_CALL.mark(element)
}
else -> {
return super.mark(element)
}
}
}
}
@JvmField val DECLARATION_RETURN_TYPE: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtDeclaration): List {
return markElement(getElementToMark(element))
}
override fun isValid(element: KtDeclaration): Boolean {
return !hasSyntaxErrors(getElementToMark(element))
}
private fun getElementToMark(declaration: KtDeclaration): PsiElement {
val (returnTypeRef, nameIdentifierOrPlaceholder) = when (declaration) {
is KtCallableDeclaration -> Pair(declaration.typeReference, declaration.nameIdentifier)
is KtPropertyAccessor -> Pair(declaration.getReturnTypeReference(), declaration.getNamePlaceholder())
else -> Pair(null, null)
}
if (returnTypeRef != null) return returnTypeRef
if (nameIdentifierOrPlaceholder != null) return nameIdentifierOrPlaceholder
return declaration
}
}
@JvmField val DECLARATION_NAME: PositioningStrategy = object : DeclarationHeader() {
override fun mark(element: KtNamedDeclaration): List {
val nameIdentifier = element.nameIdentifier
if (nameIdentifier != null) {
if (element is KtClassOrObject) {
val startElement =
element.getModifierList()?.getModifier(KtTokens.ENUM_KEYWORD)
?: element.node.findChildByType(TokenSet.create(KtTokens.CLASS_KEYWORD, KtTokens.OBJECT_KEYWORD))?.psi
?: element
return markRange(startElement, nameIdentifier)
}
return markElement(nameIdentifier)
}
if (element is KtNamedFunction) {
return DECLARATION_SIGNATURE.mark(element)
}
return DEFAULT.mark(element)
}
}
@JvmField val DECLARATION_SIGNATURE: PositioningStrategy = object : DeclarationHeader() {
override fun mark(element: KtDeclaration): List {
when (element) {
is KtConstructor<*> -> {
val begin = element.getConstructorKeyword() ?: element.getValueParameterList() ?: return markElement(element)
val end = element.getValueParameterList() ?: element.getConstructorKeyword() ?: return markElement(element)
return markRange(begin, end)
}
is KtFunction -> {
val endOfSignatureElement =
element.getTypeReference()
?: element.getValueParameterList()
?: element.getNameIdentifier()
?: element
val startElement
= if (element is KtFunctionLiteral) {
element.getReceiverTypeReference()
?: element.getValueParameterList()
?: element
}
else element
return markRange(startElement, endOfSignatureElement)
}
is KtProperty -> {
val endOfSignatureElement = element.getTypeReference() ?: element.getNameIdentifier() ?: element
return markRange(element, endOfSignatureElement)
}
is KtPropertyAccessor -> {
val endOfSignatureElement =
element.getReturnTypeReference()
?: element.getRightParenthesis()?.getPsi()
?: element.getNamePlaceholder()
return markRange(element, endOfSignatureElement)
}
is KtClass -> {
val nameAsDeclaration = element.getNameIdentifier() ?: return markElement(element)
val primaryConstructorParameterList = element.getPrimaryConstructorParameterList() ?: return markElement(nameAsDeclaration)
return markRange(nameAsDeclaration, primaryConstructorParameterList)
}
is KtObjectDeclaration -> {
return DECLARATION_NAME.mark(element)
}
}
return super.mark(element)
}
}
@JvmField val DECLARATION_SIGNATURE_OR_DEFAULT: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: PsiElement): List {
return if (element is KtDeclaration)
DECLARATION_SIGNATURE.mark(element)
else
DEFAULT.mark(element)
}
override fun isValid(element: PsiElement): Boolean {
return if (element is KtDeclaration)
DECLARATION_SIGNATURE.isValid(element)
else
DEFAULT.isValid(element)
}
}
@JvmField val TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtDeclaration): List {
if (element is KtTypeParameterListOwner) {
val jetTypeParameterList = element.typeParameterList
if (jetTypeParameterList != null) {
return markElement(jetTypeParameterList)
}
}
return DECLARATION_SIGNATURE.mark(element)
}
}
@JvmField val ABSTRACT_MODIFIER: PositioningStrategy = modifierSetPosition(KtTokens.ABSTRACT_KEYWORD)
@JvmField val OVERRIDE_MODIFIER: PositioningStrategy = modifierSetPosition(KtTokens.OVERRIDE_KEYWORD)
@JvmField val PRIVATE_MODIFIER: PositioningStrategy = modifierSetPosition(KtTokens.PRIVATE_KEYWORD)
@JvmField val VARIANCE_MODIFIER: PositioningStrategy = modifierSetPosition(KtTokens.IN_KEYWORD, KtTokens.OUT_KEYWORD)
@JvmField val FOR_REDECLARATION: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: PsiElement): List {
val nameIdentifier = when (element) {
is KtNamedDeclaration -> element.nameIdentifier
is KtFile -> element.packageDirective!!.getNameIdentifier()
else -> null
}
if (nameIdentifier == null && element is KtObjectDeclaration) return DEFAULT.mark(element)
return markElement(nameIdentifier ?: element)
}
}
@JvmField val FOR_UNRESOLVED_REFERENCE: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtReferenceExpression): List {
if (element is KtArrayAccessExpression) {
val ranges = element.bracketRanges
if (!ranges.isEmpty()) {
return ranges
}
}
return listOf(element.getCalleeHighlightingRange())
}
}
@JvmStatic fun modifierSetPosition(vararg tokens: KtModifierKeywordToken): PositioningStrategy {
return object : PositioningStrategy() {
override fun mark(element: KtModifierListOwner): List {
val modifierList = element.modifierList.sure { "No modifier list, but modifier has been found by the analyzer" }
for (token in tokens) {
val modifier = modifierList.getModifier(token)
if (modifier != null) {
return markElement(modifier)
}
}
throw IllegalStateException("None of the modifiers is found: " + listOf(*tokens))
}
}
}
@JvmField val ARRAY_ACCESS: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtArrayAccessExpression): List {
return markElement(element.indicesNode)
}
}
@JvmField val VISIBILITY_MODIFIER: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtModifierListOwner): List {
val visibilityTokens = listOf(KtTokens.PRIVATE_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.PUBLIC_KEYWORD, KtTokens.INTERNAL_KEYWORD)
val modifierList = element.modifierList
val result = visibilityTokens.mapNotNull { modifierList?.getModifier(it)?.getTextRange() }
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.nameIdentifier
if (nameIdentifier != null) {
return markElement(nameIdentifier)
}
}
val elementToMark = when (element) {
is KtObjectDeclaration -> element.getObjectKeyword()
is KtPropertyAccessor -> element.getNamePlaceholder()
is KtAnonymousInitializer -> element
else -> throw IllegalArgumentException(
"Can't find text range for element '${element.javaClass.getCanonicalName()}' with the text '${element.getText()}'")
}
return markElement(elementToMark)
}
}
@JvmField val VARIANCE_IN_PROJECTION: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtTypeProjection): List {
return markElement(element.getProjectionToken()!!)
}
}
@JvmField val PARAMETER_DEFAULT_VALUE: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtParameter): List {
return markNode(element.getDefaultValue()!!.node)
}
}
@JvmField val PARAMETER_VARARG_MODIFIER: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtParameter): List {
val varargModifier = element.modifierList!!.getModifier(KtTokens.VARARG_KEYWORD)!!
return markNode(varargModifier.node)
}
}
@JvmField val CALL_ELEMENT: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: PsiElement): List {
return markElement((element as? KtCallElement)?.calleeExpression ?: element)
}
}
@JvmField val DECLARATION_WITH_BODY: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtDeclarationWithBody): List {
val lastBracketRange = (element.bodyExpression as? KtBlockExpression)?.getLastBracketRange()
return if (lastBracketRange != null)
markRange(lastBracketRange)
else
markElement(element)
}
override fun isValid(element: KtDeclarationWithBody): Boolean {
return super.isValid(element) && (element.bodyExpression as? KtBlockExpression)?.getLastBracketRange() != null
}
}
@JvmField val VAL_OR_VAR_NODE: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtNamedDeclaration): List {
return when (element) {
is KtParameter -> markElement(element.valOrVarKeyword ?: element)
is KtProperty -> markElement(element.valOrVarKeyword)
else -> error("Declaration is neither a parameter nor a property: " + element.getElementTextWithContext())
}
}
}
@JvmField val ELSE_ENTRY: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtWhenEntry): List {
return markElement(element.elseKeyword!!)
}
}
@JvmField val WHEN_EXPRESSION: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtWhenExpression): List {
return markElement(element.whenKeyword)
}
}
@JvmField val WHEN_CONDITION_IN_RANGE: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtWhenConditionInRange): List {
return markElement(element.operationReference)
}
}
@JvmField val SPECIAL_CONSTRUCT_TOKEN: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtExpression): List =
when (element) {
is KtWhenExpression -> markElement(element.whenKeyword)
is KtIfExpression -> markElement(element.ifKeyword)
is KtOperationExpression -> markElement(element.operationReference)
else -> error("Expression is not an if, when or operation expression: ${element.getElementTextWithContext()}")
}
}
@JvmField val NULLABLE_TYPE: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtNullableType): List {
return markNode(element.getQuestionMarkNode())
}
}
@JvmField val CALL_EXPRESSION: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: PsiElement): List {
if (element is KtCallExpression) {
return markRange(element, element.getTypeArgumentList() ?: element.getCalleeExpression() ?: element)
}
return markElement(element)
}
}
@JvmField val VALUE_ARGUMENTS: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtElement): List {
return markElement((element as? KtValueArgumentList)?.rightParenthesis ?: element)
}
}
@JvmField val FUNCTION_PARAMETERS: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtFunction): List {
val valueParameterList = element.valueParameterList
if (valueParameterList != null) {
return markElement(valueParameterList)
}
if (element is KtFunctionLiteral) {
return markNode(element.getLBrace().node)
}
return DECLARATION_SIGNATURE_OR_DEFAULT.mark(element)
}
}
@JvmField val CUT_CHAR_QUOTES: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtElement): List {
if (element is KtConstantExpression) {
if (element.node.elementType == KtNodeTypes.CHARACTER_CONSTANT) {
val elementTextRange = element.getTextRange()
return listOf(TextRange.create(elementTextRange.startOffset + 1, elementTextRange.endOffset - 1))
}
}
return markElement(element)
}
}
@JvmField val LONG_LITERAL_SUFFIX: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtElement): List {
if (element is KtConstantExpression) {
if (element.node.elementType == KtNodeTypes.INTEGER_CONSTANT) {
val endOffset = element.endOffset
return listOf(TextRange.create(endOffset - 1, endOffset))
}
}
return markElement(element)
}
}
@JvmField val UNREACHABLE_CODE: PositioningStrategy = object : PositioningStrategy() {
override fun markDiagnostic(diagnostic: ParametrizedDiagnostic): List {
return Errors.UNREACHABLE_CODE.cast(diagnostic).getA()
}
}
@JvmField val AS_TYPE: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtBinaryExpressionWithTypeRHS): List {
return markRange(element.operationReference, element)
}
}
@JvmField val COMPANION_OBJECT: PositioningStrategy = object : PositioningStrategy() {
override fun mark(element: KtObjectDeclaration): List {
if (element.hasModifier(KtTokens.COMPANION_KEYWORD)) {
return modifierSetPosition(KtTokens.COMPANION_KEYWORD).mark(element)
}
return DEFAULT.mark(element)
}
}
@JvmField val SECONDARY_CONSTRUCTOR_DELEGATION_CALL: PositioningStrategy =
object : PositioningStrategy() {
override fun mark(element: KtConstructorDelegationCall): List {
if (element.isImplicit) {
val constructor = element.getStrictParentOfType()!!
val valueParameterList = constructor.getValueParameterList() ?: return markElement(constructor)
return markRange(constructor.getConstructorKeyword(), valueParameterList.getLastChild())
}
return markElement(element.calleeExpression ?: element)
}
}
@JvmField val DELEGATOR_SUPER_CALL: PositioningStrategy = object: PositioningStrategy() {
override fun mark(element: KtEnumEntry): List {
val specifiers = element.getSuperTypeListEntries()
return markElement(if (specifiers.isEmpty()) element else specifiers[0])
}
}
@JvmField val UNUSED_VALUE: PositioningStrategy = object: PositioningStrategy() {
override fun mark(element: KtBinaryExpression): List {
return listOf(TextRange(element.left!!.startOffset, element.operationReference.endOffset))
}
}
@JvmField val USELESS_ELVIS: PositioningStrategy = object: PositioningStrategy() {
override fun mark(element: KtBinaryExpression): List {
return listOf(TextRange(element.operationReference.startOffset, element.endOffset))
}
}
@JvmField val IMPORT_ALIAS: PositioningStrategy = object: PositioningStrategy() {
override fun mark(element: KtImportDirective): List {
element.aliasNameNode?.let { return markNode(it) }
element.importedReference?.let {
if (it is KtQualifiedExpression) {
it.selectorExpression?.let { return markElement(it) }
}
return markElement(it)
}
return markElement(element)
}
}
}