-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Moved some functions from PsiAnalyzerUtil to the common module and pa…
…rameterized tests
- Loading branch information
Showing
10 changed files
with
359 additions
and
505 deletions.
There are no files selected for viewing
39 changes: 39 additions & 0 deletions
39
...n/src/main/kotlin/org/jetbrains/academy/test/system/ij/analyzer/PsiElementAnalyzerUtil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package org.jetbrains.academy.test.system.ij.analyzer | ||
|
||
import com.intellij.psi.PsiElement | ||
|
||
/** | ||
* Retrieves the constant value of the PsiElement. | ||
* | ||
* @param constantExpressionClass The classes of the constant expressions to search for. | ||
* @return The constant value as a string, or null if no constant value is found. | ||
* @throws IllegalArgumentException If the PsiElement contains multiple constant values. | ||
*/ | ||
fun <T : PsiElement> PsiElement.getConstValue(vararg constantExpressionClass: Class<out T>): String? { | ||
val possibleValue = extractElementsOfTypes(*constantExpressionClass) | ||
if (possibleValue.isEmpty()) { | ||
return null | ||
} | ||
require(possibleValue.size == 1) { "Parser error! A const variable must have only one value" } | ||
return possibleValue.first().text.trimIndent() | ||
} | ||
|
||
/** | ||
* Retrieves the body of a block represented by the given code block class. | ||
* | ||
* @param codeBlockClass the class representing the code block | ||
* @return the body of the block as a string, or null if nobody is found | ||
*/ | ||
fun <T : PsiElement> PsiElement.getBlockBody(codeBlockClass: Class<T>): String? { | ||
val possibleBody = extractElementsOfTypes(codeBlockClass) | ||
if (possibleBody.isEmpty()) { | ||
return null | ||
} | ||
return possibleBody.first().text.trimBraces().trimIndent() | ||
} | ||
|
||
/** | ||
* Trims leading and trailing braces from a string. | ||
*/ | ||
private fun String.trimBraces() = dropWhile { it.isWhitespace() }.removePrefix("{") | ||
.dropLastWhile { it.isWhitespace() }.removeSuffix("}") |
87 changes: 87 additions & 0 deletions
87
...mmon/src/main/kotlin/org/jetbrains/academy/test/system/ij/analyzer/PsiFileAnalyzerUtil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package org.jetbrains.academy.test.system.ij.analyzer | ||
|
||
import com.intellij.openapi.application.ApplicationManager | ||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.PsiFile | ||
import com.intellij.psi.PsiNamedElement | ||
import com.intellij.psi.util.PsiTreeUtil | ||
import com.intellij.psi.util.parentsOfType | ||
|
||
/** Extracts elements of given type from related files in project. */ | ||
fun <T : PsiElement> PsiElement.extractElementsOfTypes(vararg psiElementClass: Class<out T>): MutableCollection<T> = | ||
psiElementClass.flatMap { PsiTreeUtil.collectElementsOfType(this, it) }.toMutableList() | ||
|
||
/** | ||
* Checks if the PsiFile contains an element of the specified type and with the given name. | ||
* | ||
* @param T the type of the PsiNamedElement subclass to check for | ||
* @param psiElementClass the class object representing the type of the element to check for | ||
* @param name the name of the element to search for | ||
* @return true if an element of the specified type and name exists in the PsiFile, false otherwise | ||
*/ | ||
fun <T : PsiNamedElement> PsiFile.hasElementOfTypeWithName(psiElementClass: Class<out T>, name: String): Boolean = | ||
ApplicationManager.getApplication().runReadAction<Boolean> { | ||
extractElementsOfTypes(psiElementClass).any { it.name == name } | ||
} | ||
|
||
/** | ||
* Retrieves the text of the parent element of the given element. | ||
* | ||
* @param element The element for which to retrieve the parent text. | ||
* @param isParentTypeFunction True if the parent element's type is a function; false otherwise. | ||
* @param parentClass The class of the parent element. | ||
* @return The text of the parent element, or null if the parent does not exist or is not of the specified type. | ||
*/ | ||
private fun <T : PsiNamedElement> getParentText( | ||
element: PsiElement, | ||
isParentTypeFunction: Boolean, | ||
parentClass: Class<out T> | ||
): String? { | ||
return if (isParentTypeFunction) { | ||
element.parentsOfType(parentClass).firstOrNull()?.name | ||
} else { | ||
element.parent?.text | ||
} | ||
} | ||
|
||
/** | ||
* Checks if the given PsiFile has an expression with the specified parent. | ||
* | ||
* @param expression The text of the expression to search for. | ||
* @param parent The text of the parent to compare with. | ||
* @param isParentTypeFunction Specifies if the parent should be treated as a function or not. | ||
* @param parentClass The class of the parent element. | ||
* @param expressionClass The classes of the expression elements to search for. | ||
* @return true if the PsiFile has an expression with the specified parent, false otherwise. | ||
*/ | ||
fun <T : PsiElement, V : PsiNamedElement> PsiFile.hasExpressionWithParent( | ||
expression: String, | ||
parent: String?, | ||
isParentTypeFunction: Boolean, | ||
parentClass: Class<out V>, | ||
vararg expressionClass: Class<out T> | ||
): Boolean = | ||
ApplicationManager.getApplication().runReadAction<Boolean> { | ||
val expressions: MutableCollection<PsiElement> = extractElementsOfTypes(*expressionClass) | ||
expressions.any { it.text == expression && getParentText(it, isParentTypeFunction, parentClass) == parent } | ||
} | ||
|
||
/** | ||
* Finds usages of a given method in the PSI file. | ||
* | ||
* @param methodName The name of the method to find usages of. | ||
* @param callExpressionClass The class representing the call expression to search for. | ||
* @param methodClass The class representing the method to search for usages of. | ||
* @return A list of strings representing the names of the methods in which the given method is used. | ||
*/ | ||
fun <T : PsiElement, V : PsiNamedElement> PsiFile.findMethodUsages( | ||
methodName: String, | ||
callExpressionClass: Class<T>, | ||
methodClass: Class<V> | ||
): List<String> = | ||
ApplicationManager.getApplication().runReadAction<List<String>> { | ||
val callExpression = extractElementsOfTypes(callExpressionClass) | ||
callExpression.filter { it.text == methodName }.mapNotNull { | ||
it.parentsOfType(methodClass).firstOrNull()?.name | ||
}.toList() | ||
} |
196 changes: 0 additions & 196 deletions
196
.../src/main/kotlin/org/jetbrains/academy/test/system/java/ij/analyzer/IjCodeAnalyzerUtil.kt
This file was deleted.
Oops, something went wrong.
57 changes: 57 additions & 0 deletions
57
...src/main/kotlin/org/jetbrains/academy/test/system/java/ij/analyzer/PsiFileAnalyzerUtil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package org.jetbrains.academy.test.system.java.ij.analyzer | ||
|
||
import com.intellij.ide.highlighter.JavaFileType | ||
import com.intellij.openapi.application.ApplicationManager | ||
import com.intellij.openapi.project.Project | ||
import com.intellij.psi.PsiFile | ||
import com.intellij.psi.PsiField | ||
import com.intellij.psi.PsiMethod | ||
import com.intellij.psi.PsiFileFactory | ||
import com.intellij.psi.PsiLiteralExpression | ||
import com.intellij.psi.PsiCodeBlock | ||
import org.jetbrains.academy.test.system.ij.analyzer.extractElementsOfTypes | ||
import org.jetbrains.academy.test.system.ij.analyzer.getBlockBody | ||
import org.jetbrains.academy.test.system.ij.analyzer.getConstValue | ||
import org.jetbrains.academy.test.system.ij.formatting.formatting | ||
|
||
/** | ||
* Checks if PsiFile contains a constant property with the given element value. | ||
* | ||
* @param elementValue The value to search for in the constant properties. | ||
* @return true if a constant property with the specified value is found, false otherwise. | ||
*/ | ||
fun PsiFile.hasConstantWithGivenValue(elementValue: String): Boolean = | ||
ApplicationManager.getApplication().runReadAction<Boolean> { | ||
val elements = extractElementsOfTypes(PsiField::class.java) | ||
elements.any { it.modifierList?.text?.contains("final") ?: false && it.getConstValue(PsiLiteralExpression::class.java) == elementValue } | ||
} | ||
|
||
/** | ||
* Formatting code content. | ||
* | ||
* @param content The source code to wrap and format. | ||
* @param project An instance of the project, used for creating PsiFile. | ||
* @return The formatted code content. | ||
*/ | ||
private fun formattingContent(content: String, project: Project): String { | ||
val wrappedCode = "class WrappedClass { void wrappedMethod() { $content } }" | ||
val factory = PsiFileFactory.getInstance(project) | ||
val contentPsiFile = factory.createFileFromText("Content.java", JavaFileType.INSTANCE, wrappedCode) | ||
val formattingContent = contentPsiFile.formatting() ?: "" | ||
return formattingContent.lines().drop(2).dropLast(2).joinToString(System.lineSeparator()).trimIndent() | ||
} | ||
|
||
/** | ||
* Finds methods within the given PsiFile that have the specified body content. | ||
* | ||
* @param content The body content to search for in the methods. | ||
* @return A list of method names whose bodies match the provided content. | ||
*/ | ||
fun PsiFile.findMethodsWithContent(content: String): List<String> = | ||
ApplicationManager.getApplication().runReadAction<List<String>> { | ||
formatting() | ||
val formattingContent = formattingContent(content, project) | ||
|
||
val methods = extractElementsOfTypes(PsiMethod::class.java) | ||
methods.filter { it.getBlockBody(PsiCodeBlock::class.java) == formattingContent }.mapNotNull { it.name }.toList() | ||
} |
Oops, something went wrong.