/* * Copyright 2003-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.idea.core.psi.impl.file; import com.intellij.lang.Language; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.FileViewProvider; import com.intellij.psi.FileViewProviderFactory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.SingleRootFileViewProvider; import com.intellij.testFramework.LightVirtualFile; import jetbrains.mps.fileTypes.MPSFileTypeFactory; import jetbrains.mps.fileTypes.MPSLanguage; import jetbrains.mps.ide.project.ProjectHelper; import jetbrains.mps.idea.core.psi.MPSNodeFileViewProvider; import jetbrains.mps.idea.core.psi.MPSSingleRootFileViewProvider; import jetbrains.mps.idea.core.psi.impl.MPSPsiModel; import jetbrains.mps.idea.core.psi.impl.MPSPsiProvider; import jetbrains.mps.idea.core.psi.impl.MPSPsiRootNode; import jetbrains.mps.nodefs.MPSNodeVirtualFile; import jetbrains.mps.smodel.ModelAccessHelper; import jetbrains.mps.smodel.SModelFileTracker; import jetbrains.mps.util.Computable; import jetbrains.mps.vfs.FileSystem; import jetbrains.mps.vfs.IFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.module.SRepository; /** * User: fyodor * Date: 2/5/13 */ public class MPSFileViewProviderFactory implements FileViewProviderFactory { @Override public FileViewProvider createFileViewProvider(@NotNull VirtualFile file, Language language, @NotNull final PsiManager manager, boolean physical) { // return new MyFileViewProvider(manager, file, physical); if (!(file instanceof MPSNodeVirtualFile)) { // todo revert to exception here, we should never be called with files like .mps (de-register their type from being MPSLanguage) // throw new IllegalStateException(); return null; } return new MPSNodeFileViewProvider(manager, (MPSNodeVirtualFile) file); } private static class MyFileViewProvider extends MPSSingleRootFileViewProvider { public MyFileViewProvider(PsiManager manager, VirtualFile file, boolean physical) { super(manager, file, physical); } private MyFileViewProvider(PsiManager manager, VirtualFile copy, boolean b, Language baseLanguage) { super(manager, copy, b, baseLanguage); } @NotNull @Override public Language getBaseLanguage() { return MPSLanguage.INSTANCE; } @NotNull @Override public SingleRootFileViewProvider createCopy(@NotNull VirtualFile copy) { // TODO proper copy? return new MyFileViewProvider(getManager(), copy, false, getBaseLanguage()); } @Override protected PsiFile createFile() { final VirtualFile virtualFile = getVirtualFile() instanceof LightVirtualFile ? ((LightVirtualFile) getVirtualFile()).getOriginalFile() : getVirtualFile(); if (virtualFile == null || (virtualFile.getFileType() != MPSFileTypeFactory.MPS_FILE_TYPE && virtualFile.getFileType() != MPSFileTypeFactory.MPS_ROOT_FILE_TYPE)) { return null; } final IFile modelFile = virtualFile.getFileType() == MPSFileTypeFactory.MPS_ROOT_FILE_TYPE ? FileSystem.getInstance().getFileByPath(virtualFile.getParent().getPath()) : FileSystem.getInstance().getFileByPath(virtualFile.getPath()); SRepository repository = ProjectHelper.getProjectRepository(getManager().getProject()); PsiFile psiFile = new ModelAccessHelper(repository.getModelAccess()).runReadAction(new Computable<PsiFile>() { @Override public PsiFile compute() { SModel descr = SModelFileTracker.getInstance(repository).findModel(modelFile); if (descr != null) { // force loading the model and updating the PSI tree at this time MPSPsiProvider mpsPsiProvider = MPSPsiProvider.getInstance(getManager().getProject()); MPSPsiModel psiModel = mpsPsiProvider.getPsi(descr); if (virtualFile.getFileType() == MPSFileTypeFactory.MPS_ROOT_FILE_TYPE) { for (PsiElement element : psiModel.getChildren()) { if (((MPSPsiRootNode) element).getVirtualFile().equals(virtualFile) || ((MPSPsiRootNode) element).getVirtualFile().getName().equals(virtualFile.getNameWithoutExtension())) { return (MPSPsiRootNode) element; } } return null; } return new FileSourcePsiFile(MyFileViewProvider.this, descr.getReference(), descr.getModelName()); } return null; } }); return psiFile; } } }