Merge remote-tracking branch 'origin/master'

This commit is contained in:
James Strachan
2012-01-25 11:57:51 +00:00
27 changed files with 290 additions and 174 deletions
@@ -40,19 +40,19 @@ public abstract class ClassBodyCodegen {
this.v = v;
}
public final void generate(@Nullable HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
public final void generate() {
generateDeclaration();
generateClassBody();
generateSyntheticParts(accessors);
generateSyntheticParts();
generateStaticInitializer();
}
protected abstract void generateDeclaration();
protected void generateSyntheticParts(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
protected void generateSyntheticParts() {
}
private void generateClassBody() {
@@ -51,11 +51,12 @@ public class ClassCodegen {
private void generateImplementation(CodegenContext context, JetClassOrObject aClass, OwnerKind kind, HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors, ClassBuilder classBuilder) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
CodegenContext classContext = context.intoClass(descriptor, kind, state.getTypeMapper());
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate(accessors);
classContext.copyAccessors(accessors);
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
ClassBuilder traitBuilder = state.forTraitImplementation(descriptor);
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state.getTypeMapper()), traitBuilder, state).generate(null);
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state.getTypeMapper()), traitBuilder, state).generate();
traitBuilder.done();
}
}
@@ -264,6 +264,15 @@ public abstract class CodegenContext {
public abstract boolean isStatic();
public void copyAccessors(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
if(accessors != null) {
if(this.accessors == null) {
this.accessors = new HashMap<DeclarationDescriptor,DeclarationDescriptor>();
}
this.accessors.putAll(accessors);
}
}
public abstract static class ReceiverContext extends CodegenContext {
final CallableDescriptor receiverDescriptor;
@@ -145,7 +145,7 @@ public class GenerationState {
closure.name = nameAndVisitor.getFirst();
final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION, typeMapper);
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null);
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
@@ -206,10 +206,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
@Override
protected void generateSyntheticParts(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
protected void generateSyntheticParts() {
generateFieldForObjectInstance();
generateFieldForClassObject();
generateAccessors(accessors);
try {
generatePrimaryConstructor();
@@ -222,98 +221,104 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
generateGetTypeInfo();
generateAccessors();
}
private void generateAccessors(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
if(accessors != null) {
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) {
if(entry.getValue() instanceof FunctionDescriptor) {
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
private void generateAccessors() {
if(context.accessors != null) {
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : context.accessors.entrySet()) {
genAccessor(entry);
}
}
}
Method method = typeMapper.mapSignature(bridge.getName(), bridge).getAsmMethod();
Method originalMethod = typeMapper.mapSignature(original.getName(), original).getAsmMethod();
Type[] argTypes = method.getArgumentTypes();
private void genAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) {
if(entry.getValue() instanceof FunctionDescriptor) {
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null);
if (v.generateCode()) {
mv.visitCode();
Method method = typeMapper.mapSignature(bridge.getName(), bridge).getAsmMethod();
Method originalMethod = typeMapper.mapSignature(original.getName(), original).getAsmMethod();
Type[] argTypes = method.getArgumentTypes();
InstructionAdapter iv = new InstructionAdapter(mv);
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null);
if (v.generateCode()) {
mv.visitCode();
iv.load(0, JetTypeMapper.TYPE_OBJECT);
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
}
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
}
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
}
}
else if(entry.getValue() instanceof PropertyDescriptor) {
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
{
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
JvmPropertyAccessorSignature originalSignature = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(), originalSignature.getJvmMethodSignature().getKotlinTypeParameter());
if (v.generateCode()) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
if(original.getVisibility() == Visibility.PRIVATE)
iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getReturnType().getDescriptor());
else
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
}
}
else if(entry.getValue() instanceof PropertyDescriptor) {
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
{
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
JvmPropertyAccessorSignature originalSignature = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(), originalSignature.getJvmMethodSignature().getKotlinTypeParameter());
if (v.generateCode()) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
if(original.getVisibility() == Visibility.PRIVATE)
iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getReturnType().getDescriptor());
else
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
}
}
{
Method method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
JvmPropertyAccessorSignature originalSignature2 = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(), originalSignature2.getJvmMethodSignature().getKotlinTypeParameter());
if (v.generateCode()) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
Type[] argTypes = method.getArgumentTypes();
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
}
if(original.getVisibility() == Visibility.PRIVATE)
iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getArgumentTypes()[0].getDescriptor());
else
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
}
}
}
else {
throw new UnsupportedOperationException();
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
}
}
if(bridge.isVar())
{
Method method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
JvmPropertyAccessorSignature originalSignature2 = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(), originalSignature2.getJvmMethodSignature().getKotlinTypeParameter());
if (v.generateCode()) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
Type[] argTypes = method.getArgumentTypes();
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
}
if(original.getVisibility() == Visibility.PRIVATE)
iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getArgumentTypes()[0].getDescriptor());
else
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
}
}
}
else {
throw new UnsupportedOperationException();
}
}
@@ -22,6 +22,7 @@ import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.*;
@@ -154,7 +155,7 @@ public class CompileEnvironment {
}
private List<Module> runDefineModules(String moduleFile, ClassFileFactory factory) {
ClassLoader loader = myStdlib != null ? new GeneratedClassLoader(factory, new URLClassLoader(new URL[] {myStdlib})) : new GeneratedClassLoader(factory);
ClassLoader loader = myStdlib != null ? new GeneratedClassLoader(factory, new URLClassLoader(new URL[] {myStdlib}, AllModules.class.getClassLoader())) : new GeneratedClassLoader(factory);
try {
Class namespaceClass = loader.loadClass(JvmAbi.PACKAGE_CLASS);
final Method method = namespaceClass.getDeclaredMethod("project");
@@ -165,7 +166,9 @@ public class CompileEnvironment {
method.setAccessible(true);
method.invoke(null);
return AllModules.modules;
ArrayList<Module> answer = new ArrayList<Module>(AllModules.modules);
AllModules.modules.clear();
return answer;
} catch (Exception e) {
throw new ModuleExecutionException(e);
}
@@ -20,6 +20,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
private static final TokenSet WHEN_CONDITION_RECOVERY_SET = TokenSet.create(RBRACE, IN_KEYWORD, NOT_IN, IS_KEYWORD, NOT_IS, ELSE_KEYWORD);
private static final TokenSet WHEN_CONDITION_RECOVERY_SET_WITH_ARROW = TokenSet.create(RBRACE, IN_KEYWORD, NOT_IN, IS_KEYWORD, NOT_IS, ELSE_KEYWORD, ARROW, DOT);
private static final ImmutableMap<String, JetToken> KEYWORD_TEXTS = tokenSetToMap(KEYWORDS);
private static ImmutableMap<String, JetToken> tokenSetToMap(TokenSet tokens) {
@@ -1406,9 +1407,9 @@ public class JetExpressionParsing extends AbstractJetParsing {
parseControlStructureBody();
}
expect(WHILE_KEYWORD, "Expecting 'while' followed by a post-condition");
parseCondition();
if (expect(WHILE_KEYWORD, "Expecting 'while' followed by a post-condition")) {
parseCondition();
}
loop.done(DO_WHILE);
}
@@ -46,7 +46,12 @@ public class JetPsiFactory {
@NotNull
public static JetFile createFile(Project project, String text) {
return (JetFile) PsiFileFactory.getInstance(project).createFileFromText("dummy.jet", JetFileType.INSTANCE, text, LocalTimeCounter.currentTime(), true);
return createFile(project, "dummy.jet", text);
}
@NotNull
public static JetFile createFile(Project project, String fileName, String text) {
return (JetFile) PsiFileFactory.getInstance(project).createFileFromText(fileName, JetFileType.INSTANCE, text, LocalTimeCounter.currentTime(), true);
}
public static JetProperty createProperty(Project project, String name, String type, boolean isVar) {
@@ -0,0 +1,50 @@
import java.util.ArrayList
public object SomeObject {
private val workerThread = object : Thread() {
override fun run() {
foo()
}
}
{
workerThread.start()
}
private fun foo() : Unit {
}
}
public class SomeClass() {
class Inner {
val copy = list
}
private val list = ArrayList<String>()
var status : Throwable? = null
private val workerThread = object : Thread() {
public override fun run() {
try {
list.add("123")
list.add("33")
Inner().copy.add("444")
}
catch(t: Throwable) {
status = t
}
}
}
{
workerThread.start()
workerThread.join()
}
}
public fun box():String {
var obj = SomeClass()
return if(obj.status == null) "OK" else {
obj.status?.printStackTrace()
"failed"
}
}
@@ -165,31 +165,16 @@ public class JetTestUtils {
}
}
public static void rmrf(File file) {
if (file != null) {
FileUtil.delete(file);
}
public static File tmpDirForTest(TestCase test) throws IOException {
File answer = FileUtil.createTempDirectory(test.getClass().getSimpleName(), test.getName());
deleteOnShutdown(answer);
return answer;
}
public static File tmpRoot() {
return new File("tmp");
}
public static File tmpDirForTest(TestCase test) {
return new File(tmpRoot(), test.getClass().getSimpleName() + "/" + test.getName());
}
public static File tmpDirForTest(Class<?> clazz) {
return tmpDirForTest(clazz.getSimpleName());
}
public static File tmpDirForTest(String name) {
return new File(tmpRoot(), name);
}
public static void recreateDirectory(File file) throws IOException {
rmrf(file);
mkdirs(file);
public static File tmpDir(String name) throws IOException {
File answer = FileUtil.createTempDirectory(name, "");
deleteOnShutdown(answer);
return answer;
}
public static void deleteOnShutdown(File file) {
@@ -30,8 +30,7 @@ public class ForTestCompileStdlib {
private static File stdlibJarFile;
private static File doCompile() throws Exception {
File tmpDir = FileUtil.createTempDirectory("stdlibjar", "");
JetTestUtils.deleteOnShutdown(tmpDir);
File tmpDir = JetTestUtils.tmpDir("stdlibjar");
File jarFile = new File(tmpDir, "stdlib.jar");
@@ -119,7 +118,7 @@ public class ForTestCompileStdlib {
public static File stdlibJarForTests() {
synchronized (ForTestCompileStdlib.class) {
if (stdlibJarFile == null) {
if (stdlibJarFile == null || !stdlibJarFile.exists()) {
try {
stdlibJarFile = doCompile();
} catch (Exception e) {
@@ -30,4 +30,8 @@ public class ObjectGenTest extends CodegenTestCase {
public void testKt640() throws Exception {
blackBoxFile("regressions/kt640.jet");
}
public void testKt1136() throws Exception {
blackBoxFile("regressions/kt1136.kt");
}
}
@@ -66,8 +66,7 @@ public class CompileEnvironmentTest extends TestCase {
File tempDir = FileUtil.createTempDirectory("compilerTest", "compilerTest");
try {
File out = new File(tempDir, "out");
File stdlib = new File(tempDir, "stdlib.jar");
FileUtil.copy(ForTestCompileStdlib.stdlibJarForTests(), stdlib);
File stdlib = ForTestCompileStdlib.stdlibJarForTests();
KotlinCompiler.exec("-src", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kt",
"-output", out.getAbsolutePath(),
"-stdlib", stdlib.getAbsolutePath());
@@ -16,7 +16,6 @@ public abstract class TestCaseWithTmpdir extends UsefulTestCase {
protected void setUp() throws Exception {
super.setUp();
tmpdir = JetTestUtils.tmpDirForTest(this);
JetTestUtils.recreateDirectory(tmpdir);
}
}
@@ -173,9 +173,10 @@ public class JetPsiChecker implements Annotator {
return;
}
// General annotation
// Generic annotation
Annotation errorAnnotation = holder.createErrorAnnotation(diagnostic.getFactory().getTextRange(diagnostic), getMessage(diagnostic));
registerQuickFix(
holder.createErrorAnnotation(diagnostic.getFactory().getTextRange(diagnostic), getMessage(diagnostic)),
errorAnnotation,
diagnostic);
}
else if (diagnostic.getSeverity() == Severity.WARNING) {
@@ -2,9 +2,9 @@ package org.jetbrains.jet.plugin.formatter;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.TokenType;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.formatter.common.AbstractBlock;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
@@ -16,15 +16,14 @@ import java.util.Collections;
import java.util.List;
/**
* @see Block for good JavaDoc documentation
* @author yole
*/
public class JetBlock implements ASTBlock {
private ASTNode myNode;
private Alignment myAlignment;
public class JetBlock extends AbstractBlock {
private Indent myIndent;
private Wrap myWrap;
private CodeStyleSettings mySettings;
private final SpacingBuilder mySpacingBuilder;
private List<Block> mySubBlocks;
private static final TokenSet CODE_BLOCKS = TokenSet.create(
@@ -35,52 +34,35 @@ public class JetBlock implements ASTBlock {
private static final TokenSet STATEMENT_PARTS = TokenSet.create(
JetNodeTypes.THEN,
JetNodeTypes.ELSE);
// private static final List<IndentWhitespaceRule>
public JetBlock(ASTNode node, Alignment alignment, Indent indent, Wrap wrap, CodeStyleSettings settings,
SpacingBuilder spacingBuilder) {
myNode = node;
myAlignment = alignment;
public JetBlock(@NotNull ASTNode node,
Alignment alignment,
Indent indent,
Wrap wrap,
CodeStyleSettings settings,
SpacingBuilder spacingBuilder) {
super(node, wrap, alignment);
myIndent = indent;
myWrap = wrap;
mySettings = settings;
mySpacingBuilder = spacingBuilder;
}
@Override
public ASTNode getNode() {
return myNode;
}
@NotNull
@Override
public TextRange getTextRange() {
return myNode.getTextRange();
}
@Override
public Wrap getWrap() {
return myWrap;
}
@Override
public Indent getIndent() {
return myIndent;
}
@Override
public Alignment getAlignment() {
return myAlignment;
}
@NotNull
@Override
public List<Block> getSubBlocks() {
protected List<Block> buildChildren() {
if (mySubBlocks == null) {
mySubBlocks = buildSubBlocks();
}
return new ArrayList<Block>(mySubBlocks);
}
private List<Block> buildSubBlocks() {
List<Block> blocks = new ArrayList<Block>();
for (ASTNode child = myNode.getFirstChildNode(); child != null; child = child.getTreeNext()) {
@@ -97,7 +79,8 @@ public class JetBlock implements ASTBlock {
return Collections.unmodifiableList(blocks);
}
private Block buildSubBlock(ASTNode child) {
@NotNull
private Block buildSubBlock(@NotNull ASTNode child) {
Wrap wrap = null;
Indent childIndent = Indent.getNoneIndent();
Alignment childAlignment = null;
@@ -128,7 +111,7 @@ public class JetBlock implements ASTBlock {
return new JetBlock(child, childAlignment, childIndent, wrap, mySettings, mySpacingBuilder);
}
private static Indent indentIfNotBrace(ASTNode child) {
private static Indent indentIfNotBrace(@NotNull ASTNode child) {
return child.getElementType() == JetTokens.RBRACE || child.getElementType() == JetTokens.LBRACE
? Indent.getNoneIndent()
: Indent.getNormalIndent();
@@ -151,16 +134,18 @@ public class JetBlock implements ASTBlock {
@NotNull
@Override
public ChildAttributes getChildAttributes(int newChildIndex) {
Indent childIndent = Indent.getNoneIndent();
if (CODE_BLOCKS.contains(myNode.getElementType()) || myNode.getElementType() == JetNodeTypes.WHEN) {
childIndent = Indent.getNormalIndent();
}
return new ChildAttributes(childIndent, null);
}
final IElementType type = getNode().getElementType();
if (CODE_BLOCKS.contains(type) ||
type == JetNodeTypes.WHEN ||
type == JetNodeTypes.IF ||
type == JetNodeTypes.FOR ||
type == JetNodeTypes.WHILE ||
type == JetNodeTypes.DO_WHILE) {
@Override
public boolean isIncomplete() {
return false;
return new ChildAttributes(Indent.getNormalIndent(), null);
}
return new ChildAttributes(Indent.getNoneIndent(), null);
}
@Override
@@ -0,0 +1,4 @@
fun some() {
do
<caret>
}
@@ -0,0 +1,3 @@
fun some() {
do<caret>
}
@@ -0,0 +1,3 @@
fun some() {
for (var i in 1..10)
<caret>
@@ -0,0 +1,2 @@
fun some() {
for (var i in 1..10)<caret>
@@ -0,0 +1,4 @@
fun some() {
if (3 > 5)
<caret>
}
@@ -0,0 +1,3 @@
fun some() {
if (3 > 5)<caret>
}
@@ -0,0 +1,4 @@
fun some() {
var t = 12
while (t > 0)
<caret>
@@ -0,0 +1,3 @@
fun some() {
var t = 12
while (t > 0)<caret>
@@ -39,7 +39,7 @@ import java.util.Map;
// Based on from com.intellij.psi.formatter.java.AbstractJavaFormatterTest
@SuppressWarnings("UnusedDeclaration")
public abstract class AbstractKotlinFormatterTest extends LightIdeaTestCase {
public abstract class AbstractJetFormatterTest extends LightIdeaTestCase {
protected enum Action {REFORMAT, INDENT}
@@ -96,6 +96,10 @@ public abstract class AbstractKotlinFormatterTest extends LightIdeaTestCase {
doTextTest(Action.REFORMAT, text, textAfter);
}
public void doIndentTextTest(@NonNls final String text, @NonNls String textAfter) throws IncorrectOperationException {
doTextTest(Action.INDENT, text, textAfter);
}
public void doTextTest(final Action action, final String text, String textAfter) throws IncorrectOperationException {
final PsiFile file = createFile("A.kt", text);
@@ -3,7 +3,7 @@ package org.jetbrains.jet.formatter;
/**
* Based on com.intellij.psi.formatter.java.JavaFormatterTest
*/
public class KotlinFormatterTest extends AbstractKotlinFormatterTest {
public class JetFormatterTest extends AbstractJetFormatterTest {
public void testBlockFor() throws Exception {
doTest();
}
@@ -0,0 +1,40 @@
package org.jetbrains.jet.formatter;
import com.intellij.testFramework.LightCodeInsightTestCase;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.File;
/**
* @author Nikolay Krasko
*/
public class JetTypingIndentationTest extends LightCodeInsightTestCase {
public void testWhile() {
doFileNewlineTest();
}
public void testFor() {
doFileNewlineTest();
}
public void testIf() {
doFileNewlineTest();
}
public void testDoInFun() {
doFileNewlineTest();
}
public void doFileNewlineTest() {
configureByFile(getTestName(false) + ".kt");
type('\n');
checkResultByFile(getTestName(false) + ".after.kt");
}
@Override
protected String getTestDataPath() {
final String testRelativeDir = "formatter/IndentationOnNewline";
return new File(PluginTestCaseBase.getTestDataPathBase(), testRelativeDir).getPath() +
File.separator;
}
}