package com.siberika.idea.pascal.lang.compiled;
import com.intellij.extapi.psi.LightPsiFileBase;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiCompiledFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.PsiFileEx;
import com.intellij.psi.impl.file.PsiFileImplUtil;
import com.intellij.psi.impl.source.LightPsiFileImpl;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.util.IncorrectOperationException;
import com.siberika.idea.pascal.PascalFileType;
import com.siberika.idea.pascal.PascalLanguage;
import org.jetbrains.annotations.NotNull;
/**
* Author: George Bakhtadze
* Date: 14/11/2013
*/
abstract class CompiledFileImpl extends LightPsiFileBase implements PsiFileEx, PsiCompiledFile {
private static final String DECOMPILED_FILENAME_PREFIX = "$";
private volatile TreeElement myMirrorFileElement;
private final PsiManager myManager;
public CompiledFileImpl(PsiManager myManager, FileViewProvider provider) {
super(provider, PascalLanguage.INSTANCE);
this.myManager = myManager;
}
@Override
public void clearCaches() {
synchronized (CompiledFileImpl.class) {
myMirrorFileElement = null;
}
}
@NotNull
@Override
public PsiElement[] getChildren() {
return getMirror().getChildren();
}
@Override
public void delete() throws IncorrectOperationException {
checkDelete();
PsiFileImplUtil.doDelete(this);
}
@Override
public LightPsiFileImpl copyLight(FileViewProvider viewProvider) {
return null;
}
@Override
public PsiFile getDecompiledPsiFile() {
return (PsiFile) getMirror();
}
@Override
public PsiDirectory getContainingDirectory() {
VirtualFile parentFile = getVirtualFile().getParent();
if (parentFile == null) return null;
return getManager().findDirectory(parentFile);
}
@Override
@NotNull
public VirtualFile getVirtualFile() {
return getViewProvider().getVirtualFile();
}
@Override
public PsiElement getMirror() {
synchronized (CompiledFileImpl.class) {
if (myMirrorFileElement == null) {
String ext = PascalFileType.INSTANCE.getDefaultExtension();
String fileName = DECOMPILED_FILENAME_PREFIX + getVirtualFile().getNameWithoutExtension() + "." + ext;
PsiFileFactory factory = PsiFileFactory.getInstance(getManager().getProject());
PsiFile mirror = factory.createFileFromText(fileName, PascalLanguage.INSTANCE, decompile(getManager(), getVirtualFile()), false, false);
if (mirror instanceof PsiFileImpl) {
((PsiFileImpl) mirror).setOriginalFile(this);
}
myMirrorFileElement = SourceTreeToPsiMap.psiToTreeNotNull(mirror);
}
return myMirrorFileElement.getPsi();
}
}
public abstract String decompile(PsiManager manager, VirtualFile file);
}