Skip to content

Commit

Permalink
Added support for type and return type modifiers.
Browse files Browse the repository at this point in the history
  • Loading branch information
andreihh committed Mar 3, 2018
1 parent 3575c50 commit d04a857
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 24 deletions.
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
buildscript {
ext {
kotlin_version = '1.2.21'
dokka_version = '0.9.15'
jackson_version = '2.9.4'
kotlin_version = '1.2.30'
dokka_version = '0.9.16'
jackson_version = '2.9.4.1'
jdt_version = '3.13.100'
junit_version = '4.12'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,28 @@ fun SourceNode.walkSourceTree(): List<SourceNode> {
return nodes
}

private const val typePrefix = "@type:"
private const val returnTypePrefix = "@return:"

/** Returns the type of this variable, or `null` if not specified. */
val Variable.type: String?
get() = modifiers
.singleOrNull { it.startsWith(typePrefix) }
?.removePrefix(typePrefix)

/** Returns the return type of this function, or `null` if not specified. */
val Function.returnType: String?
get() = modifiers
.singleOrNull { it.startsWith(returnTypePrefix) }
?.removePrefix(returnTypePrefix)

/** Returns the modifier corresponding to the given [type]. */
fun typeModifierOf(type: String): String = "$typePrefix$type"

/** Returns the modifier corresponding to the given [returnType]. */
fun returnTypeModifierOf(returnType: String): String =
"$returnTypePrefix$returnType"

internal fun NodeHashMap.putSourceTree(root: SourceNode) {
this += root.walkSourceTree().associateBy(SourceNode::id)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.metanalysis.test.core.model.sourceUnit
import org.metanalysis.test.core.model.type
import org.metanalysis.test.core.model.variable
import kotlin.test.assertEquals
import kotlin.test.assertNull

class UtilsTest {
@Test fun `test children of unit are equal to entities`() {
Expand Down Expand Up @@ -60,4 +61,30 @@ class UtilsTest {
val node = variable("$path:getVersion(String):name") {}
assertEquals(path, node.sourcePath)
}

@Test fun `test return type`() {
val returnType = "int"
val function = function("src/Test.java:getVersion()") {
modifiers("public", returnTypeModifierOf(returnType))
}
assertEquals(returnType, function.returnType)
}

@Test fun `test null return type`() {
val function = function("src/Test.java:getVersion()") {}
assertNull(function.returnType)
}

@Test fun `test variable type`() {
val variableType = "String"
val variable = variable("src/Test.java:VERSION") {
modifiers("public", typeModifierOf(variableType))
}
assertEquals(variableType, variable.type)
}

@Test fun `test null variable type`() {
val variable = variable("src/Test.java:VERSION") {}
assertNull(variable.type)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import org.metanalysis.core.model.SourceNode.Companion.ENTITY_SEPARATOR
import org.metanalysis.core.model.SourceUnit
import org.metanalysis.core.model.Type
import org.metanalysis.core.model.Variable
import org.metanalysis.core.model.returnTypeModifierOf
import org.metanalysis.core.model.typeModifierOf

internal data class ParserContext(
private val unitId: String,
Expand All @@ -40,8 +42,18 @@ internal data class ParserContext(
private fun ASTNode.toSource(): String =
source.substring(startPosition, startPosition + length)

private fun ASTNode.modifierSet(): Set<String> =
getModifiers(this).map { it.toSource() }.requireDistinct()
private fun ASTNode.modifierSet(): Set<String> {
val additionalModifier = when (this) {
is AbstractTypeDeclaration -> typeModifier()
is MethodDeclaration -> returnType()?.let(::returnTypeModifierOf)
else -> type()?.let(::typeModifierOf)
}
val modifiers = getModifiers(this)
.map { it.toSource() }
.requireDistinct()
return if (additionalModifier == null) modifiers
else modifiers + additionalModifier
}

private fun AbstractTypeDeclaration.supertypeSet(): Set<String> =
supertypes().map { it.toSource() }.requireDistinct()
Expand Down Expand Up @@ -80,7 +92,7 @@ internal data class ParserContext(
return Type(
id = id,
supertypes = node.supertypeSet(),
modifiers = node.modifierSet() + node.typeModifier(),
modifiers = node.modifierSet(),
members = members.toSet()
)
}
Expand Down
31 changes: 29 additions & 2 deletions metanalysis-java/src/main/kotlin/org/metanalysis/java/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,37 @@ internal fun AnnotationTypeMemberDeclaration.name(): String = name.identifier
internal fun EnumConstantDeclaration.name(): String = name.identifier
internal fun VariableDeclaration.name(): String = name.identifier

private fun Type?.asString(
extraDimensions: Int = 0,
isVarargs: Boolean = false
): String? {
val suffix = "[]".repeat(extraDimensions) + if (isVarargs) "..." else ""
return if (this == null) null else "$this$suffix" // TODO: stringify type
}

private fun getBaseType(node: ASTNode): Type? = when (node) {
is FieldDeclaration -> node.type
is AnnotationTypeMemberDeclaration -> node.type
is SingleVariableDeclaration -> node.type
is VariableDeclarationFragment -> getBaseType(node.parent)
else -> null
}

internal fun ASTNode.type(): String? = when (this) {
is SingleVariableDeclaration ->
getBaseType(this).asString(extraDimensions, isVarargs)
is VariableDeclarationFragment ->
getBaseType(this).asString(extraDimensions)
else -> getBaseType(this).asString()
}

internal fun MethodDeclaration.returnType(): String? =
returnType2.asString(extraDimensions)

internal fun MethodDeclaration.signature(): String {
val parameterList = getParameters(this).joinToString { parameter ->
val postfix = if (parameter.isVarargs) "..." else ""
"${parameter.type}$postfix"
parameter.type()
?: throw AssertionError("'$parameter' must have specified type!")
}
return "${name.identifier}($parameterList)"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.metanalysis.java

import org.junit.Test
import org.metanalysis.core.model.typeModifierOf
import kotlin.test.assertEquals

class JavaParserAnnotationTest : JavaParserTest() {
Expand All @@ -43,8 +44,12 @@ class JavaParserAnnotationTest : JavaParserTest() {
val expected = sourceUnit {
type("AnnotationClass") {
modifiers("@interface")
variable("name") {}
variable("version") {}
variable("name") {
modifiers(typeModifierOf("String"))
}
variable("version") {
modifiers(typeModifierOf("int"))
}
}
}
assertEquals(expected, parse(source))
Expand All @@ -60,8 +65,13 @@ class JavaParserAnnotationTest : JavaParserTest() {
val expected = sourceUnit {
type("AnnotationClass") {
modifiers("@interface")
variable("name") {}
variable("version") { +"1" }
variable("name") {
modifiers(typeModifierOf("String"))
}
variable("version") {
modifiers(typeModifierOf("int"))
+"1"
}
}
}
assertEquals(expected, parse(source))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package org.metanalysis.java

import org.junit.Test
import org.metanalysis.core.model.returnTypeModifierOf
import org.metanalysis.core.model.typeModifierOf
import kotlin.test.assertEquals

class JavaParserClassTest : JavaParserTest() {
Expand Down Expand Up @@ -46,9 +48,15 @@ class JavaParserClassTest : JavaParserTest() {
modifiers("abstract", "class")

function("println(String...)") {
parameter("args") {}
modifiers(
"@Override",
"abstract",
returnTypeModifierOf("void")
)

modifiers("abstract", "@Override")
parameter("args") {
modifiers(typeModifierOf("String..."))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package org.metanalysis.java

import org.junit.Test
import org.metanalysis.core.model.returnTypeModifierOf
import org.metanalysis.core.model.typeModifierOf
import kotlin.test.assertEquals

class JavaParserEnumTest : JavaParserTest() {
Expand Down Expand Up @@ -70,12 +72,12 @@ class JavaParserEnumTest : JavaParserTest() {
variable("GREEN") {}
variable("BLUE") {}
variable("format") {
modifiers("public", "final")
modifiers("public", "final", typeModifierOf("String"))

+"\"hex\""
}
variable("i") {
modifiers("public", "static")
modifiers("public", "static", typeModifierOf("int"))
}
}
}
Expand Down Expand Up @@ -136,7 +138,7 @@ class JavaParserEnumTest : JavaParserTest() {
}

function("getCode()") {
modifiers("abstract")
modifiers("abstract", returnTypeModifierOf("String"))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.metanalysis.java

import org.junit.Test
import org.metanalysis.core.model.typeModifierOf
import org.metanalysis.core.parsing.Result
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
Expand Down Expand Up @@ -78,7 +79,9 @@ class JavaParserErrorTest : JavaParserTest() {
val expected = sourceUnit {
type("Type") {
modifiers("class")
variable("i") {}
variable("i") {
modifiers(typeModifierOf("int"))
}
}
}
val result = parseResult(source)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package org.metanalysis.java

import org.junit.Test
import org.metanalysis.core.model.returnTypeModifierOf
import org.metanalysis.core.model.typeModifierOf
import kotlin.test.assertEquals

class JavaParserInterfaceTest : JavaParserTest() {
Expand All @@ -43,8 +45,14 @@ class JavaParserInterfaceTest : JavaParserTest() {
val expected = sourceUnit {
type("IInterface") {
modifiers("interface")
variable("name") { +"null" }
variable("version") { +"1" }
variable("name") {
modifiers(typeModifierOf("String"))
+"null"
}
variable("version") {
modifiers(typeModifierOf("int"))
+"1"
}
}
}
assertEquals(expected, parse(source))
Expand All @@ -60,8 +68,12 @@ class JavaParserInterfaceTest : JavaParserTest() {
val expected = sourceUnit {
type("IInterface") {
modifiers("interface")
function("getName()") {}
function("getVersion()") {}
function("getName()") {
modifiers(returnTypeModifierOf("String"))
}
function("getVersion()") {
modifiers(returnTypeModifierOf("int"))
}
}
}
assertEquals(expected, parse(source))
Expand All @@ -79,9 +91,11 @@ class JavaParserInterfaceTest : JavaParserTest() {
val expected = sourceUnit {
type("IInterface") {
modifiers("interface")
function("getName()") {}
function("getName()") {
modifiers(returnTypeModifierOf("String"))
}
function("getVersion()") {
modifiers("default")
modifiers("default", returnTypeModifierOf("int"))

+"{"
+"return 1;"
Expand Down

0 comments on commit d04a857

Please sign in to comment.