Skip to content

Commit

Permalink
Merge pull request #172 from illided/nullable_properties
Browse files Browse the repository at this point in the history
Nullable properties
  • Loading branch information
SpirinEgor authored Aug 5, 2021
2 parents f8741c8 + a8124bd commit f23862a
Show file tree
Hide file tree
Showing 16 changed files with 156 additions and 97 deletions.
6 changes: 3 additions & 3 deletions src/main/kotlin/astminer/common/model/FunctionInfoModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ interface FunctionInfo<T : Node> {
get() = notImplemented("root")
val filePath: String
get() = notImplemented("filePath")
val annotations: List<String>
val annotations: List<String>?
get() = notImplemented("annotations")
val modifiers: List<String>
val modifiers: List<String>?
get() = notImplemented("modifiers")
val parameters: List<FunctionInfoParameter>
val parameters: List<FunctionInfoParameter>?
get() = notImplemented("parameters")
val returnType: String?
get() = notImplemented("returnType")
Expand Down
14 changes: 9 additions & 5 deletions src/main/kotlin/astminer/filters/FunctionFilters.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@ import astminer.common.splitToSubtokens
* Filter that excludes functions that have at least one of modifiers from the [excludeModifiers] list.
*/
class ModifierFilter(private val excludeModifiers: List<String>) : FunctionFilter {
override fun validate(functionInfo: FunctionInfo<out Node>): Boolean =
!excludeModifiers.any { modifier -> modifier in functionInfo.modifiers }
override fun validate(functionInfo: FunctionInfo<out Node>): Boolean {
val functionModifiers = checkNotNull(functionInfo.modifiers) { "Modifiers weren't properly parsed" }
return functionModifiers.none { modifier -> modifier in excludeModifiers }
}
}

/**
* Filter that excludes functions that have at least one annotations from the [excludeAnnotations] list.
* Filter that excludes functions that have at least one of annotations from the [excludeAnnotations] list.
*/
class AnnotationFilter(private val excludeAnnotations: List<String>) : FunctionFilter {
override fun validate(functionInfo: FunctionInfo<out Node>): Boolean =
!excludeAnnotations.any { annotation -> annotation in functionInfo.annotations }
override fun validate(functionInfo: FunctionInfo<out Node>): Boolean {
val functionAnnotations = checkNotNull(functionInfo.annotations) { "Annotations weren't properly parsed" }
return functionAnnotations.none { annotation -> annotation in excludeAnnotations }
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@ package astminer.parse.antlr.java
import astminer.common.model.*
import astminer.parse.antlr.*
import astminer.parse.findEnclosingElementBy
import mu.KotlinLogging

private val logger = KotlinLogging.logger("Antlr-Java-function-info")

class AntlrJavaFunctionInfo(override val root: AntlrNode, override val filePath: String) : FunctionInfo<AntlrNode> {
override val nameNode: AntlrNode? = collectNameNode()
override val parameters: List<FunctionInfoParameter> = collectParameters()
override val returnType: String? = collectReturnType()
override val enclosingElement: EnclosingElement<AntlrNode>? = collectEnclosingClass()

override val parameters: List<FunctionInfoParameter>? =
try { collectParameters() } catch (e: IllegalStateException) {
logger.warn { e.message }
null
}

private fun collectNameNode(): AntlrNode? = root.getChildOfType(METHOD_NAME_NODE)

private fun collectReturnType(): String? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package astminer.parse.antlr.javascript
import astminer.common.model.*
import astminer.parse.antlr.*
import astminer.parse.findEnclosingElementBy
import mu.KotlinLogging

private val logger = KotlinLogging.logger("Antlr-Javascript-function-info")

/**
Base class for describing JavaScript methods, functions or arrow functions.
Expand Down Expand Up @@ -76,9 +79,14 @@ abstract class AntlrJavaScriptElementInfo(override val root: AntlrNode, override
class JavaScriptArrowInfo(root: AntlrNode, filePath: String) : AntlrJavaScriptElementInfo(root, filePath) {

override val enclosingElement: EnclosingElement<AntlrNode>? = collectEnclosingElement()
override val parameters: List<FunctionInfoParameter> = collectParameters()
override val nameNode: AntlrNode? = root.getChildOfType(ARROW_NAME_NODE)

override val parameters: List<FunctionInfoParameter>? =
try { collectParameters() } catch (e: IllegalStateException) {
logger.warn { e.message }
null
}

override fun getParametersRoot(): AntlrNode? {
val parameterRoot = root.getChildOfType(ARROW_PARAMETER_NODE)
return parameterRoot?.getChildOfType(ARROW_PARAMETER_INNER_NODE) ?: parameterRoot
Expand All @@ -94,8 +102,12 @@ class JavaScriptArrowInfo(root: AntlrNode, filePath: String) : AntlrJavaScriptEl
class JavaScriptMethodInfo(root: AntlrNode, filePath: String) : AntlrJavaScriptElementInfo(root, filePath) {

override val enclosingElement: EnclosingElement<AntlrNode>? = collectEnclosingElement()
override val parameters: List<FunctionInfoParameter> = collectParameters()
override val nameNode: AntlrNode? = collectNameNode()
override val parameters: List<FunctionInfoParameter>? =
try { collectParameters() } catch (e: IllegalStateException) {
logger.warn { e.message }
null
}

private fun collectNameNode(): AntlrNode? {
val methodNameParent = root.children.firstOrNull {
Expand All @@ -119,8 +131,12 @@ class JavaScriptMethodInfo(root: AntlrNode, filePath: String) : AntlrJavaScriptE
class JavaScriptFunctionInfo(root: AntlrNode, filePath: String) : AntlrJavaScriptElementInfo(root, filePath) {

override val enclosingElement: EnclosingElement<AntlrNode>? = collectEnclosingElement()
override val parameters: List<FunctionInfoParameter> = collectParameters()
override val nameNode: AntlrNode? = root.getChildOfType(FUNCTION_NAME_NODE)
override val parameters: List<FunctionInfoParameter>? =
try { collectParameters() } catch (e: IllegalStateException) {
logger.warn { e.message }
null
}

override fun getParametersRoot(): AntlrNode? = root.getChildOfType(FUNCTION_PARAMETER_NODE)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ private val logger = KotlinLogging.logger("ANTLR-PHP-function-info")
class ANTLRPHPFunctionInfo(override val root: AntlrNode, override val filePath: String) : FunctionInfo<AntlrNode> {
override val returnType = getElementType(root)
override val nameNode: AntlrNode? = root.getChildOfType(FUNCTION_NAME)

override val parameters: List<FunctionInfoParameter> = collectParameters()
override val enclosingElement: EnclosingElement<AntlrNode>? = collectEnclosingElement()
override val parameters: List<FunctionInfoParameter>? =
try { collectParameters() } catch (e: IllegalStateException) {
logger.warn { e.message }
null
}

private fun collectParameters(): List<FunctionInfoParameter> {
// Parameters in this grammar have following structure (children order may be wrong):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ package astminer.parse.antlr.python
import astminer.common.model.*
import astminer.parse.antlr.*
import astminer.parse.findEnclosingElementBy
import mu.KotlinLogging

private val logger = KotlinLogging.logger("Antlr-python-function-info")

class AntlrPythonFunctionInfo(override val root: AntlrNode, override val filePath: String) : FunctionInfo<AntlrNode> {
override val nameNode: AntlrNode? = collectNameNode()
override val parameters: List<FunctionInfoParameter> = collectParameters()
override val enclosingElement: EnclosingElement<AntlrNode>? = collectEnclosingElement()
override val parameters: List<FunctionInfoParameter>? =
try { collectParameters() } catch (e: IllegalStateException) {
logger.warn { e.message }
null
}

private fun collectNameNode(): AntlrNode? = root.getChildOfType(FUNCTION_NAME_NODE)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ import astminer.common.model.FunctionInfo
import astminer.common.model.FunctionInfoParameter
import astminer.parse.findEnclosingElementBy
import astminer.parse.fuzzy.FuzzyNode
import mu.KotlinLogging

private val logger = KotlinLogging.logger("Fuzzyparser-Cpp-function-info")

class FuzzyCppFunctionInfo(override val root: FuzzyNode, override val filePath: String) : FunctionInfo<FuzzyNode> {

override val returnType: String? = collectReturnType()
override val enclosingElement: EnclosingElement<FuzzyNode>? = collectEnclosingClass()
override val parameters: List<FunctionInfoParameter> = collectParameters()
override val nameNode: FuzzyNode? = collectNameNode()
override val parameters: List<FunctionInfoParameter>? =
try { collectParameters() } catch (e: IllegalStateException) {
logger.warn { e.message }
null
}

private fun collectNameNode(): FuzzyNode? = root.getChildOfType(METHOD_NAME_NODE) as? FuzzyNode

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,23 @@ import astminer.common.model.EnclosingElementType
import astminer.common.model.FunctionInfo
import astminer.common.model.FunctionInfoParameter
import astminer.parse.gumtree.GumTreeNode
import mu.KotlinLogging

private val logger = KotlinLogging.logger("Gumtree-Java-function-info")

class GumTreeJavaFunctionInfo(
override val root: GumTreeNode,
override val filePath: String
) : FunctionInfo<GumTreeNode> {

override val nameNode: GumTreeNode? = root.getChildOfType(TypeLabels.simpleName)
override val parameters: List<FunctionInfoParameter> = collectParameters()
override val returnType: String? = root.getElementType()
override val enclosingElement: EnclosingElement<GumTreeNode>? = collectEnclosingClass()
override val parameters: List<FunctionInfoParameter>? =
try { collectParameters() } catch (e: IllegalStateException) {
logger.warn { e.message }
null
}

override val modifiers: List<String> = root.children.filter { it.typeLabel == "Modifier" }.map { it.originalToken }
override val annotations: List<String> = root
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,23 @@ import astminer.common.model.FunctionInfo
import astminer.common.model.FunctionInfoParameter
import astminer.parse.findEnclosingElementBy
import astminer.parse.gumtree.GumTreeNode
import mu.KotlinLogging

private val logger = KotlinLogging.logger("Gumtree-Java-function-info")

class GumTreePythonFunctionInfo(
override val root: GumTreeNode,
override val filePath: String
) : FunctionInfo<GumTreeNode> {

override val nameNode: GumTreeNode = root
override val parameters: List<FunctionInfoParameter> = collectParameters()
override val enclosingElement: EnclosingElement<GumTreeNode>? = collectEnclosingClass()
override val returnType: String? = getElementType(root)?.typeLabel
override val parameters: List<FunctionInfoParameter>? =
try { collectParameters() } catch (e: IllegalStateException) {
logger.warn { e.message }
null
}

private fun getElementType(node: GumTreeNode): GumTreeNode? {
if (node.typeLabel == TypeLabels.arg) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,40 +70,40 @@ class JavaFunctionSplitterTest {
fun testNoParameters() {
val methodNoParameters = functionInfos.find { it.name == "functionWithNoParameters" }
assertNotNull(methodNoParameters)
assertEquals(0, methodNoParameters.parameters.size)
assertEquals(0, methodNoParameters.parameters?.size)
}

@Test
fun testOneParameter() {
val methodOneParameter = functionInfos.find { it.name == "functionWithOneParameter" }
assertNotNull(methodOneParameter)
assertEquals(1, methodOneParameter.parameters.size)
val parameter = methodOneParameter.parameters[0]
assertEquals("p1", parameter.name)
assertEquals("int", parameter.type)
assertEquals(1, methodOneParameter.parameters?.size)
val parameter = methodOneParameter.parameters?.get(0)
assertEquals("p1", parameter?.name)
assertEquals("int", parameter?.type)
}

@Test
fun testThreeParameters() {
val methodThreeParameters = functionInfos.find { it.name == "functionWithThreeParameters" }
assertNotNull(methodThreeParameters)
assertEquals(3, methodThreeParameters.parameters.size)
assertEquals(3, methodThreeParameters.parameters?.size)
val methodTypes = listOf("Class", "String[][]", "int[]")
for (i in 0 until 3) {
val parameter = methodThreeParameters.parameters[i]
assertEquals("p${i + 1}", parameter.name)
assertEquals(methodTypes[i], parameter.type)
val parameter = methodThreeParameters.parameters?.get(i)
assertEquals("p${i + 1}", parameter?.name)
assertEquals(methodTypes[i], parameter?.type)
}
}

@Test
fun testWeirdArrayParameter() {
val methodWeirdArrayParameter = functionInfos.find { it.name == "functionWithStrangeArrayParameter" }
assertNotNull(methodWeirdArrayParameter)
assertEquals(1, methodWeirdArrayParameter.parameters.size)
val weirdParameter = methodWeirdArrayParameter.parameters[0]
assertEquals(weirdParameter.name, "arr[]")
assertEquals(weirdParameter.type, "int")
assertEquals(1, methodWeirdArrayParameter.parameters?.size)
val weirdParameter = methodWeirdArrayParameter.parameters?.get(0)
assertEquals(weirdParameter?.name, "arr[]")
assertEquals(weirdParameter?.type, "int")
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class JavaScriptFunctionSplitterTest {
fun FunctionInfo<AntlrNode>.getJsonInfo(): String {
return "info : {" +
"name : $name, " +
"args : ${parameters.joinToString(", ") { it.name }}, " +
"args : ${parameters?.joinToString(", ") { it.name }}, " +
"enclosing element : ${enclosingElement?.type?.getEnclosingElementType()}, " +
"enclosing element name : ${enclosingElement?.name}" +
"}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ internal class ANTLRPHPFunctionSplitterTest {
fun FunctionInfo<AntlrNode>.getJsonInfo(): String = listOf(
"info : {",
"name: $name, ",
"args: ${parameters.joinToString(", ") {
"args: ${parameters?.joinToString(", ") {
listOfNotNull(it.type, it.name).joinToString(" ")
}}, ",
"enclosing element: ${enclosingElement?.type?.getEnclosingElementType()}, ",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,44 +53,44 @@ class PythonFunctionSplitterTest {
fun testNoParameters() {
val functionNoParameters = functionInfos.find { it.name == "function_with_no_parameters" }
assertNotNull(functionNoParameters)
assertEquals(0, functionNoParameters.parameters.size)
assertEquals(0, functionNoParameters.parameters?.size)
}

@Test
fun testOneParameter() {
val functionOneParameter = functionInfos.find { it.name == "function_with_one_parameter" }
assertNotNull(functionOneParameter)
assertEquals(1, functionOneParameter.parameters.size)
val parameter = functionOneParameter.parameters[0]
assertEquals("p1", parameter.name)
assertEquals(1, functionOneParameter.parameters?.size)
val parameter = functionOneParameter.parameters?.get(0)
assertEquals("p1", parameter?.name)
}

@Test
fun testOneTypedParameter() {
val functionOneTypedParameter = functionInfos.find { it.name == "function_with_one_typed_parameter" }
assertNotNull(functionOneTypedParameter)
assertEquals(1, functionOneTypedParameter.parameters.size)
val parameter = functionOneTypedParameter.parameters[0]
assertEquals("p1", parameter.name)
assertEquals("int", parameter.type)
assertEquals(1, functionOneTypedParameter.parameters?.size)
val parameter = functionOneTypedParameter.parameters?.get(0)
assertEquals("p1", parameter?.name)
assertEquals("int", parameter?.type)
}

@Test
fun functionWithComplexParameter() {
val functionOneTypedParameter = functionInfos.find { it.name == "function_with_complex_parameter" }
assertNotNull(functionOneTypedParameter)
assertEquals(1, functionOneTypedParameter.parameters.size)
val parameter = functionOneTypedParameter.parameters[0]
assertEquals("p1", parameter.name)
assertEquals("List[int]", parameter.type)
assertEquals(1, functionOneTypedParameter.parameters?.size)
val parameter = functionOneTypedParameter.parameters?.get(0)
assertEquals("p1", parameter?.name)
assertEquals("List[int]", parameter?.type)
}

@Test
fun testThreeParameters() {
val functionThreeParameters = functionInfos.find { it.name == "function_with_three_parameters" }
assertNotNull(functionThreeParameters)
assertEquals(3, functionThreeParameters.parameters.size)
val parameters = functionThreeParameters.parameters
assertEquals(3, functionThreeParameters.parameters?.size)
val parameters = functionThreeParameters.parameters!!
assertEquals("p1", parameters[0].name)

assertEquals("p2", parameters[1].name)
Expand All @@ -103,19 +103,19 @@ class PythonFunctionSplitterTest {
fun testParameterInClass() {
val functionOneParameter = functionInfos.find { it.name == "fun_with_parameter_in_class" }
assertNotNull(functionOneParameter)
assertEquals(2, functionOneParameter.parameters.size)
val parameter = functionOneParameter.parameters[1]
assertEquals("p1", parameter.name)
assertEquals(2, functionOneParameter.parameters?.size)
val parameter = functionOneParameter.parameters?.get(1)
assertEquals("p1", parameter?.name)
}

@Test
fun testTypedParameterInClass() {
val functionOneTypedParameter = functionInfos.find { it.name == "fun_with_typed_parameter_in_class" }
assertNotNull(functionOneTypedParameter)
assertEquals(2, functionOneTypedParameter.parameters.size)
val parameter = functionOneTypedParameter.parameters[1]
assertEquals("p1", parameter.name)
assertEquals("int", parameter.type)
assertEquals(2, functionOneTypedParameter.parameters?.size)
val parameter = functionOneTypedParameter.parameters?.get(1)
assertEquals("p1", parameter?.name)
assertEquals("int", parameter?.type)
}

@Test
Expand Down
Loading

0 comments on commit f23862a

Please sign in to comment.