Java to Kotlin converter: better comments preserving, never lose any comment

#KT-4489 Fixed
This commit is contained in:
Valentin Kipyatkov
2014-06-20 14:30:37 +04:00
parent ef62600d5e
commit 116c27117f
20 changed files with 157 additions and 111 deletions
@@ -21,6 +21,7 @@ import java.util.HashSet
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
import java.util.ArrayList
import org.jetbrains.jet.j2k.ast.Element
import org.jetbrains.jet.j2k.ast.Modifiers
import kotlin.platform.platformName
fun<T> CodeBuilder.append(generators: Collection<() -> T>, separator: String, prefix: String = "", suffix: String = ""): CodeBuilder {
@@ -104,6 +105,17 @@ class CodeBuilder(private val topElement: PsiElement?) {
element.generateCode(this)
// scan for all comments inside which are not yet used in the text and put them here to not loose any comment from code
for ((prototype, _) in element.prototypes) {
prototype.accept(object : JavaRecursiveElementVisitor(){
override fun visitComment(comment: PsiComment) {
if (commentsAndSpacesUsed.add(comment)) {
append(comment.getText()!!, comment.isEndOfLineComment())
}
}
})
}
postfixElements.forEach { append(it.getText()!!, it.isEndOfLineComment()) }
return this
+17 -17
View File
@@ -168,7 +168,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
private fun convertClass(psiClass: PsiClass): Class {
val annotations = convertAnnotations(psiClass)
val modifiers = convertModifiers(psiClass)
var modifiers = convertModifiers(psiClass)
val typeParameters = convertTypeParameterList(psiClass.getTypeParameterList())
val implementsTypes = convertToNotNullableTypes(psiClass.getImplementsListTypes())
val extendsTypes = convertToNotNullableTypes(psiClass.getExtendsListTypes())
@@ -198,11 +198,11 @@ public class Converter private(val project: Project, val settings: ConverterSett
}
if (settings.openByDefault && !psiClass.hasModifierProperty(PsiModifier.FINAL)) {
modifiers.add(Modifier.OPEN)
modifiers = modifiers.with(Modifier.OPEN)
}
if (psiClass.getContainingClass() != null && !psiClass.hasModifierProperty(PsiModifier.STATIC)) {
modifiers.add(Modifier.INNER)
modifiers = modifiers.with(Modifier.INNER)
}
Class(name, annotations, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, classBody)
@@ -247,7 +247,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
val initializer = MethodCallExpression.buildNotNull(null, className.name, finalOrWithEmptyInitializerFields.map { initializers[it]!! })
val localVar = LocalVariable(SecondaryConstructor.tempValIdentifier,
Annotations.Empty,
setOf(),
Modifiers.Empty,
{ ClassType(className, listOf(), Nullability.NotNull, settings) },
initializer,
true,
@@ -259,10 +259,10 @@ public class Converter private(val project: Project, val settings: ConverterSett
//TODO: comments?
val parameters = finalOrWithEmptyInitializerFields.map { field ->
val varValModifier = if (field.isVal) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var
Parameter(field.identifier, field.`type`, varValModifier, field.annotations, field.modifiers.filter { ACCESS_MODIFIERS.contains(it) })
Parameter(field.identifier, field.`type`, varValModifier, field.annotations, field.modifiers.filter { it in ACCESS_MODIFIERS })
}
val primaryConstructor = PrimaryConstructor(this, Annotations.Empty, setOf(Modifier.PRIVATE), ParameterList(parameters), Block.Empty)
val primaryConstructor = PrimaryConstructor(this, Annotations.Empty, Modifiers(listOf(Modifier.PRIVATE)), ParameterList(parameters), Block.Empty)
val updatedMembers = classBody.normalMembers.filter { !finalOrWithEmptyInitializerFields.contains(it) }
return ClassBody(primaryConstructor, classBody.secondaryConstructors, updatedMembers, classBody.classObjectMembers, classBody.lBrace, classBody.rBrace)
}
@@ -302,7 +302,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
val returnType = typeConverter.convertMethodReturnType(method)
val annotations = convertAnnotations(method) + convertThrows(method)
val modifiers = convertModifiers(method)
var modifiers = convertModifiers(method)
if (method.isConstructor()) {
if (method.isPrimaryConstructor()) {
@@ -316,7 +316,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
else {
val isOverride = isOverride(method)
if (isOverride) {
modifiers.add(Modifier.OVERRIDE)
modifiers = modifiers.with(Modifier.OVERRIDE)
}
val containingClass = method.getContainingClass()
@@ -325,7 +325,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
val isEffectivelyFinal = method.hasModifierProperty(PsiModifier.FINAL) ||
containingClass != null && (containingClass.hasModifierProperty(PsiModifier.FINAL) || containingClass.isEnum())
if (!isEffectivelyFinal && !modifiers.contains(Modifier.ABSTRACT) && !modifiers.contains(Modifier.PRIVATE)) {
modifiers.add(Modifier.OPEN)
modifiers = modifiers.with(Modifier.OPEN)
}
}
@@ -342,7 +342,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
ClassType(Identifier("Any"), listOf(), Nullability.Nullable, settings),
Parameter.VarValModifier.None,
params.parameters.single().annotations,
listOf())
Modifiers.Empty)
params = ParameterList(listOf(correctedParameter))
}
}
@@ -390,7 +390,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
private fun convertPrimaryConstructor(constructor: PsiMethod,
annotations: Annotations,
modifiers: Set<Modifier>,
modifiers: Modifiers,
membersToRemove: MutableSet<PsiMember>): PrimaryConstructor {
val params = constructor.getParameterList().getParameters()
val parameterToField = HashMap<PsiParameter, Pair<PsiField, Type>>()
@@ -439,7 +439,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
`type`,
if (field.hasModifierProperty(PsiModifier.FINAL)) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var,
convertAnnotations(parameter) + convertAnnotations(field),
convertModifiers(field).filter { ACCESS_MODIFIERS.contains(it) }).assignPrototypes(listOf(parameter, field), inheritBlankLinesBefore = false)
convertModifiers(field).filter { it in ACCESS_MODIFIERS }).assignPrototypes(listOf(parameter, field), inheritBlankLinesBefore = false)
}
})
return PrimaryConstructor(this, annotations, modifiers, parameterList, block).assignPrototype(constructor)
@@ -521,9 +521,9 @@ public class Converter private(val project: Project, val settings: ConverterSett
= ParameterList(parameterList.getParameters().map { convertParameter(it) }).assignPrototype(parameterList)
fun convertParameter(parameter: PsiParameter,
nullability: Nullability = Nullability.Default,
varValModifier: Parameter.VarValModifier = Parameter.VarValModifier.None,
modifiers: List<Modifier> = listOf()): Parameter {
nullability: Nullability = Nullability.Default,
varValModifier: Parameter.VarValModifier = Parameter.VarValModifier.None,
modifiers: Modifiers = Modifiers.Empty): Parameter {
var `type` = typeConverter.convertVariableType(parameter)
when (nullability) {
Nullability.NotNull -> `type` = `type`.toNotNullType()
@@ -566,8 +566,8 @@ public class Converter private(val project: Project, val settings: ConverterSett
return Identifier(identifier.getText()!!).assignPrototype(identifier)
}
fun convertModifiers(owner: PsiModifierListOwner): MutableSet<Modifier>
= HashSet(MODIFIERS_MAP.filter { owner.hasModifierProperty(it.first) }.map { it.second })
fun convertModifiers(owner: PsiModifierListOwner): Modifiers
= Modifiers(MODIFIERS_MAP.filter { owner.hasModifierProperty(it.first) }.map { it.second }).assignPrototype(owner.getModifierList(), false)
private val MODIFIERS_MAP = listOf(
PsiModifier.ABSTRACT to Modifier.ABSTRACT,
@@ -24,6 +24,7 @@ import java.util.HashMap
import java.util.HashSet
import org.jetbrains.jet.j2k.ast.Import
import org.jetbrains.jet.j2k.ast.ImportList
import org.jetbrains.jet.j2k.ast.assignPrototype
class TypeConverter(val settings: ConverterSettings, val conversionScope: ConversionScope) {
private val nullabilityCache = HashMap<PsiElement, Nullability>()
@@ -56,7 +57,7 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
= types.map { convertType(it) }
public fun convertVariableType(variable: PsiVariable): Type
= convertType(variable.getType(), variableNullability(variable))
= convertType(variable.getType(), variableNullability(variable)).assignPrototype(variable.getTypeElement())
public fun variableNullability(variable: PsiVariable): Nullability {
val cached = nullabilityCache[variable]
@@ -119,7 +120,7 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
}
public fun convertMethodReturnType(method: PsiMethod): Type
= convertType(method.getReturnType(), methodNullability(method))
= convertType(method.getReturnType(), methodNullability(method)).assignPrototype(method.getReturnTypeElement())
public fun methodNullability(method: PsiMethod): Nullability {
val cached = nullabilityCache[method]
@@ -19,7 +19,7 @@ package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CodeBuilder
class AnonymousClassBody(body: ClassBody, val extendsTrait: Boolean)
: Class(Identifier.Empty, Annotations.Empty, setOf(), TypeParameterList.Empty, listOf(), listOf(), listOf(), body) {
: Class(Identifier.Empty, Annotations.Empty, Modifiers.Empty, TypeParameterList.Empty, listOf(), listOf(), listOf(), body) {
override fun generateCode(builder: CodeBuilder) {
body.append(builder, null)
}
+8 -21
View File
@@ -16,13 +16,12 @@
package org.jetbrains.jet.j2k.ast
import java.util.ArrayList
import org.jetbrains.jet.j2k.*
open class Class(
val name: Identifier,
annotations: Annotations,
modifiers: Set<Modifier>,
modifiers: Modifiers,
val typeParameterList: TypeParameterList,
val extendsTypes: List<Type>,
val baseClassParams: List<Expression>,
@@ -32,7 +31,11 @@ open class Class(
override fun generateCode(builder: CodeBuilder) {
builder.append(annotations)
appendModifiers(builder).append(keyword).append(" ").append(name).append(typeParameterList)
.appendWithSpaceAfter(presentationModifiers())
.append(keyword)
.append(" ")
.append(name)
.append(typeParameterList)
appendPrimaryConstructorSignature(builder)
appendBaseTypes(builder)
typeParameterList.appendWhere(builder)
@@ -61,22 +64,6 @@ open class Class(
return extendsTypes.map { { builder.append(it) } }
}
protected open fun appendModifiers(builder: CodeBuilder): CodeBuilder {
val modifierList = ArrayList<Modifier>()
modifiers.accessModifier()?.let { modifierList.add(it) }
if (modifiers.contains(Modifier.ABSTRACT)) {
modifierList.add(Modifier.ABSTRACT)
}
else if (modifiers.contains(Modifier.OPEN)) {
modifierList.add(Modifier.OPEN)
}
if (modifiers.contains(Modifier.INNER)) {
modifierList.add(Modifier.INNER)
}
return builder.append(modifierList)
}
protected open fun presentationModifiers(): Modifiers
= if (modifiers.contains(Modifier.ABSTRACT)) modifiers.without(Modifier.OPEN) else modifiers
}
@@ -18,7 +18,7 @@ package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.*
abstract class Member(val annotations: Annotations, val modifiers: Set<Modifier>) : Element()
abstract class Member(val annotations: Annotations, val modifiers: Modifiers) : Element()
class ClassBody (
val primaryConstructor: PrimaryConstructor?,
@@ -16,29 +16,30 @@
package org.jetbrains.jet.j2k.ast
import java.util.HashSet
import java.util.ArrayList
import org.jetbrains.jet.j2k.*
abstract class Constructor(
converter: Converter,
annotations: Annotations,
modifiers: Set<Modifier>,
modifiers: Modifiers,
parameterList: ParameterList,
block: Block
) : Function(converter, Identifier.Empty, annotations, modifiers, Type.Empty, TypeParameterList.Empty, parameterList, block, false)
class PrimaryConstructor(converter: Converter,
annotations: Annotations,
modifiers: Set<Modifier>,
modifiers: Modifiers,
parameterList: ParameterList,
block: Block)
: Constructor(converter, annotations, modifiers, parameterList, block) {
public fun appendSignature(builder: CodeBuilder): CodeBuilder {
val accessModifier = modifiers.accessModifier()
val modifiersString = if (accessModifier != null && accessModifier != Modifier.PUBLIC) " " + accessModifier.toKotlin() else ""
return builder.append(modifiersString).append("(").append(parameterList).append(")")
val accessModifier = modifiers.filter { it in ACCESS_MODIFIERS && it != Modifier.PUBLIC }
if (!accessModifier.isEmpty) {
builder append " " append accessModifier
}
return builder append "(" append parameterList append ")"
}
public fun appendBody(builder: CodeBuilder): CodeBuilder = builder.append(block!!)
@@ -46,13 +47,12 @@ class PrimaryConstructor(converter: Converter,
class SecondaryConstructor(converter: Converter,
annotations: Annotations,
modifiers: Set<Modifier>,
modifiers: Modifiers,
parameterList: ParameterList,
block: Block)
: Constructor(converter, annotations, modifiers, parameterList, block) {
public fun toFactoryFunction(containingClass: Class?): Function {
val modifiers = HashSet(modifiers)
val statements = ArrayList(block?.statements ?: listOf())
statements.add(ReturnStatement(tempValIdentifier))
val block = Block(statements, block?.lBrace ?: LBrace(), block?.rBrace ?: RBrace())
+2 -2
View File
@@ -19,8 +19,8 @@ package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.*
import com.intellij.psi.PsiElement
fun <TElement: Element> TElement.assignPrototype(prototype: PsiElement?): TElement {
assignPrototypeInfos(if (prototype != null) listOf(PrototypeInfo(prototype, true)) else listOf())
fun <TElement: Element> TElement.assignPrototype(prototype: PsiElement?, inheritBlankLinesBefore: Boolean = true): TElement {
assignPrototypeInfos(if (prototype != null) listOf(PrototypeInfo(prototype, inheritBlankLinesBefore)) else listOf())
return this
}
+2 -3
View File
@@ -21,7 +21,7 @@ import org.jetbrains.jet.j2k.*
class Enum(
name: Identifier,
annotations: Annotations,
modifiers: Set<Modifier>,
modifiers: Modifiers,
typeParameterList: TypeParameterList,
extendsTypes: List<Type>,
baseClassParams: List<Expression>,
@@ -35,8 +35,7 @@ class Enum(
}
override fun generateCode(builder: CodeBuilder) {
builder append annotations
appendModifiers(builder) append "enum class " append name
builder append annotations appendWithSpaceAfter presentationModifiers() append "enum class " append name
appendPrimaryConstructorSignature(builder)
builder append typeParameterList
appendBaseTypes(builder)
@@ -21,7 +21,7 @@ import org.jetbrains.jet.j2k.*
class EnumConstant(
identifier: Identifier,
annotations: Annotations,
modifiers: Set<Modifier>,
modifiers: Modifiers,
`type`: Type,
params: Element
) : Field(identifier, annotations, modifiers, `type`.toNotNullType(), params, true, false) {
+2 -14
View File
@@ -17,12 +17,11 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.*
import java.util.ArrayList
open class Field(
val identifier: Identifier,
annotations: Annotations,
modifiers: Set<Modifier>,
modifiers: Modifiers,
val `type`: Type,
val initializer: Element,
val isVal: Boolean,
@@ -31,7 +30,7 @@ open class Field(
override fun generateCode(builder: CodeBuilder) {
builder.append(annotations)
.appendModifiers()
.appendWithSpaceAfter(modifiers)
.append(if (isVal) "val " else "var ")
.append(identifier)
.append(" : ")
@@ -45,15 +44,4 @@ open class Field(
builder append "=" append initializerToUse
}
}
private fun CodeBuilder.appendModifiers(): CodeBuilder {
val modifierList = ArrayList<Modifier>()
if (modifiers.contains(Modifier.ABSTRACT)) {
modifierList.add(Modifier.ABSTRACT)
}
modifiers.accessModifier()?.let { modifierList.add(it) }
return append(modifierList)
}
}
+10 -21
View File
@@ -16,14 +16,13 @@
package org.jetbrains.jet.j2k.ast
import java.util.ArrayList
import org.jetbrains.jet.j2k.*
open class Function(
val converter: Converter,
val name: Identifier,
annotations: Annotations,
modifiers: Set<Modifier>,
modifiers: Modifiers,
val `type`: Type,
val typeParameterList: TypeParameterList,
val parameterList: ParameterList,
@@ -31,33 +30,23 @@ open class Function(
val isInTrait: Boolean
) : Member(annotations, modifiers) {
private fun CodeBuilder.appendModifiers(): CodeBuilder {
val resultingModifiers = ArrayList<Modifier>()
val isOverride = modifiers.contains(Modifier.OVERRIDE)
if (isOverride) {
resultingModifiers.add(Modifier.OVERRIDE)
private fun presentationModifiers(): Modifiers {
var modifiers = this.modifiers
if (isInTrait) {
modifiers = modifiers.without(Modifier.ABSTRACT)
}
val accessModifier = modifiers.accessModifier()
if (accessModifier != null && !isOverride) {
resultingModifiers.add(accessModifier)
if (modifiers.contains(Modifier.OVERRIDE)) {
modifiers = modifiers.filter { it != Modifier.OPEN && it !in ACCESS_MODIFIERS }
}
if (modifiers.contains(Modifier.ABSTRACT) && !isInTrait) {
resultingModifiers.add(Modifier.ABSTRACT)
}
if (modifiers.contains(Modifier.OPEN) && !isOverride) {
resultingModifiers.add(Modifier.OPEN)
}
return append(resultingModifiers)
return modifiers
}
override fun generateCode(builder: CodeBuilder) {
builder.append(annotations)
.appendModifiers()
.append(" fun ")
.appendWithSpaceAfter(presentationModifiers())
.append("fun ")
.appendWithSuffix(typeParameterList, " ")
.append(name)
.append("(")
@@ -18,7 +18,7 @@ package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.*
class Initializer(val block: Block, modifiers: Set<Modifier>) : Member(Annotations.Empty, modifiers) {
class Initializer(val block: Block, modifiers: Modifiers) : Member(Annotations.Empty, modifiers) {
override fun generateCode(builder: CodeBuilder) {
builder.append(block)
}
@@ -23,7 +23,7 @@ import org.jetbrains.jet.j2k.append
class LocalVariable(
private val identifier: Identifier,
private val annotations: Annotations,
private val modifiers: Set<Modifier>,
private val modifiers: Modifiers,
private val typeCalculator: () -> Type /* we use lazy type calculation for better performance */,
private val initializer: Expression,
private val isVal: Boolean,
+32 -8
View File
@@ -16,7 +16,8 @@
package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CodeBuilder
import org.jetbrains.jet.j2k.*
import java.util.HashSet
enum class Modifier(val name: String) {
PUBLIC: Modifier("public")
@@ -33,16 +34,39 @@ enum class Modifier(val name: String) {
val ACCESS_MODIFIERS = setOf(Modifier.PUBLIC, Modifier.PROTECTED, Modifier.PRIVATE)
fun Collection<Modifier>.accessModifier(): Modifier? {
return firstOrNull { ACCESS_MODIFIERS.contains(it) }
return firstOrNull { it in ACCESS_MODIFIERS }
}
fun CodeBuilder.append(modifiers: List<Modifier>): CodeBuilder {
if (!modifiers.isEmpty()) {
for (modifier in modifiers) {
append(modifier.toKotlin()).append(" ")
}
class Modifiers(val modifiers: Collection<Modifier>) : Element() {
override fun generateCode(builder: CodeBuilder) {
builder.append(modifiers.sortBy { it.ordinal() }.map { it.toKotlin() }.joinToString(" "))
}
override val isEmpty: Boolean
get() = modifiers.isEmpty()
fun with(modifier: Modifier): Modifiers = Modifiers(modifiers + listOf(modifier)).assignPrototypesFrom(this)
fun without(modifier: Modifier): Modifiers {
val set = HashSet(modifiers)
set.remove(modifier)
return Modifiers(set).assignPrototypesFrom(this)
}
fun contains(modifier: Modifier): Boolean = modifiers.contains(modifier)
class object {
val Empty = Modifiers(listOf())
}
}
fun Modifiers.filter(predicate: (Modifier) -> Boolean): Modifiers
= Modifiers(modifiers.filter(predicate)).assignPrototypesFrom(this)
fun CodeBuilder.appendWithSpaceAfter(modifiers: Modifiers): CodeBuilder {
if (!modifiers.isEmpty) {
this append modifiers append " "
}
return this
}
@@ -22,7 +22,7 @@ class Parameter(val identifier: Identifier,
val `type`: Type,
val varVal: Parameter.VarValModifier,
val annotations: Annotations,
val modifiers: List<Modifier>) : Element() {
val modifiers: Modifiers) : Element() {
public enum class VarValModifier {
None
Val
@@ -30,7 +30,7 @@ class Parameter(val identifier: Identifier,
}
override fun generateCode(builder: CodeBuilder) {
builder.append(annotations).append(modifiers)
builder.append(annotations).appendWithSpaceAfter(modifiers)
if (`type` is VarArgType) {
assert(varVal == VarValModifier.None)
+3 -8
View File
@@ -16,12 +16,11 @@
package org.jetbrains.jet.j2k.ast
import java.util.ArrayList
import org.jetbrains.jet.j2k.CodeBuilder
class Trait(name: Identifier,
annotations: Annotations,
modifiers: Set<Modifier>,
modifiers: Modifiers,
typeParameterList: TypeParameterList,
extendsTypes: List<Type>,
baseClassParams: List<Expression>,
@@ -34,10 +33,6 @@ class Trait(name: Identifier,
override fun appendPrimaryConstructorSignature(builder: CodeBuilder) { }
override fun appendModifiers(builder: CodeBuilder): CodeBuilder {
val modifierList = ArrayList<Modifier>()
modifiers.accessModifier()?.let { modifierList.add(it) }
return builder.append(modifierList)
}
override fun presentationModifiers(): Modifiers
= modifiers.filter { it in ACCESS_MODIFIERS }
}
@@ -742,6 +742,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
doTest("j2k/tests/testData/ast/comments/comments.java");
}
@TestMetadata("comments2.java")
public void testComments2() throws Exception {
doTest("j2k/tests/testData/ast/comments/comments2.java");
}
@TestMetadata("fieldWithEndOfLineComment.java")
public void testFieldWithEndOfLineComment() throws Exception {
doTest("j2k/tests/testData/ast/comments/fieldWithEndOfLineComment.java");
@@ -0,0 +1,20 @@
//file
package foo;
class A {
void/* nothing to return */ foo(/* no parameters at all */) {
// let declare a variable
// with 2 comments before
int/*int*/ a /* it's a */ = 2 /* it's 2 */ + 1 /* it's 1 */; // variable a declared
} // end of foo
int/* we return int*/ foo(int/*int*/ p/* parameter p */) { /* body is empty */ }
private/*it's private*/ int field = 0;
public /*it's public*/ char foo() { }
protected/*it's protected*/ void foo() { }
public/*it's public*/ static/*and static*/ final/*and final*/ int C = 1;
}
@@ -0,0 +1,26 @@
package foo
class A() {
fun /* nothing to return */ foo(/* no parameters at all */) {
// let declare a variable
// with 2 comments before
val /*int*/ a /* it's a */ = 2 /* it's 2 */ + 1 /* it's 1 */ // variable a declared
} // end of foo
fun /* we return int*/ foo(/*int*/ p: Int/* parameter p */): Int {
/* body is empty */
}
private /*it's private*/ var field: Int = 0
public /*it's public*/ fun foo(): Char {
}
protected /*it's protected*/ fun foo() {
}
class object {
public /*it's public*//*and static*//*and final*/ val C: Int = 1
}
}