package org.jetbrains.kotlin.parser;

import java.io.File;

import org.eclipse.core.resources.IFile;
import org.jetbrains.jet.CompilerModeProvider;
import org.jetbrains.jet.OperationModeProvider;
import org.jetbrains.jet.lang.parsing.JetParser;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.JetLanguage;

import com.intellij.core.JavaCoreApplicationEnvironment;
import com.intellij.core.JavaCoreProjectEnvironment;
import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilderFactory;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;

public class KotlinParser {

    private final static Disposable DISPOSABLE = new Disposable() {
        
        @Override
        public void dispose() {
        }
    };
    
    private final File file;
    
    private final static JavaCoreApplicationEnvironment applicationEnvironment;
    private final static Project project;
    private ASTNode tree;
    
    static {
        applicationEnvironment = new JavaCoreApplicationEnvironment(DISPOSABLE);
        
        applicationEnvironment.registerFileType(JetFileType.INSTANCE, "kt");
        applicationEnvironment.registerFileType(JetFileType.INSTANCE, "jet");
        applicationEnvironment.registerParserDefinition(new JetParserDefinition());

        applicationEnvironment.getApplication().registerService(OperationModeProvider.class, new CompilerModeProvider());
        
        JavaCoreProjectEnvironment projectEnvironment = new JavaCoreProjectEnvironment(DISPOSABLE, applicationEnvironment);
        
        project = projectEnvironment.getProject();
    }
    
    public KotlinParser(File file) {
        this.file = file;
        this.tree = null;
    }
    
    public KotlinParser(IFile iFile) {
        this(new File(iFile.getRawLocation().toOSString()));
    }
    
    public static ASTNode parse(IFile iFile) {
        return new KotlinParser(iFile).parse();
    }
    
    public ASTNode parse() {
        JetParser jetParser = new JetParser(project);
        tree = jetParser.parse(null, createPsiBuilder(getNode(file)), getPsiFile(file));
        
        return tree;
    }
    
    public ASTNode getTree() {
        return  tree;
    }
    
    private PsiBuilder createPsiBuilder(ASTNode chameleon) {
        return PsiBuilderFactory.getInstance().createBuilder(project, chameleon, null, 
                JetLanguage.INSTANCE, chameleon.getChars());
    }
    
    private PsiFile getPsiFile(File file) {
        VirtualFile fileByPath = applicationEnvironment.getLocalFileSystem().findFileByPath(file.getAbsolutePath());
        
        return PsiManager.getInstance(project).findFile(fileByPath);
    }
    
    private ASTNode getNode(File file) {
        JetFile jetFile = (JetFile) getPsiFile(file);
        return jetFile.getNode();
    }
}

@@ -1086,23 +1086,16 @@
 e final 
-static 
 JavaCore
@@ -1159,23 +1159,16 @@
 e final 
-static 
 Project 
@@ -1215,16 +1215,101 @@
     
-static %7B
+public KotlinParser(File file) %7B%0A        this.file = file;%0A        this.tree = null;%0A        
 %0A   
@@ -1965,108 +1965,8 @@
    %0A
-    public KotlinParser(File file) %7B%0A        this.file = file;%0A        this.tree = null;%0A    %7D%0A    %0A
     

Refresh application environment every time when we want parse file