/*
* 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;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.project.Project;
import jetbrains.mps.ide.project.ProjectHelper;
import org.jetbrains.mps.openapi.language.SLanguage;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.model.SModel.Problem;
import org.jetbrains.mps.openapi.model.SModelListener;
import org.jetbrains.mps.openapi.model.SModelReference;
import org.jetbrains.mps.openapi.module.SDependency;
import org.jetbrains.mps.openapi.module.SModule;
import org.jetbrains.mps.openapi.module.SModuleListener;
import org.jetbrains.mps.openapi.module.SRepository;
/**
* Created by danilla on 12/23/14.
*/
public class PsiModelReloadListener extends AbstractProjectComponent implements SModelListener, SModuleListener {
private MPSPsiProvider myPsiProvider;
protected PsiModelReloadListener(Project project) {
super(project);
myPsiProvider = MPSPsiProvider.getInstance(myProject);
}
@Override
public void modelLoaded(SModel sModel, boolean b) {
}
@Override
public void modelReplaced(final SModel sModel) {
packRunnable(new Runnable() {
@Override
public void run() {
MPSPsiModel psiModel = myPsiProvider.getPsi(sModel);
if (psiModel == null) {
return;
}
psiModel.reloadAll();
myPsiProvider.notifyPsiChanged(psiModel, null);
}
});
}
@Override
public void modelUnloaded(SModel sModel) {
}
@Override
public void modelSaved(SModel sModel) {
}
@Override
public void conflictDetected(SModel sModel) {
}
@Override
public void problemsDetected(SModel sModel, Iterable<Problem> iterable) {
}
@Override
public void modelAttached(SModel model, SRepository repository) {
}
public void modelDetached(SModel model, SRepository repository) {
}
// module listener
@Override
public void modelAdded(SModule sModule, final SModel sModel) {
packRunnable(new Runnable() {
@Override
public void run() {
MPSPsiModel psiModel = myPsiProvider.getPsi(sModel);
if (psiModel == null) {
return;
}
myPsiProvider.notifyPsiChanged(psiModel, null);
}
});
}
@Override
public void beforeModelRemoved(SModule sModule, SModel sModel) {
}
@Override
public void modelRemoved(SModule sModule, SModelReference sModelReference) {
}
@Override
public void beforeModelRenamed(SModule sModule, SModel sModel, SModelReference sModelReference) {
}
@Override
public void modelRenamed(SModule sModule, final SModel sModel, final SModelReference sModelReference) {
packRunnable(new Runnable() {
@Override
public void run() {
MPSPsiModel psiModel = myPsiProvider.getPsi(sModel);
if (psiModel == null) {
return;
}
String oldName = sModelReference.getModelName();
String newName = sModel.getModelName();
myPsiProvider.notifyModelRenamed(psiModel, oldName, newName);
}
});
}
@Override
public void dependencyAdded(SModule sModule, SDependency sDependency) {
}
@Override
public void dependencyRemoved(SModule sModule, SDependency sDependency) {
}
@Override
public void languageAdded(SModule sModule, SLanguage sLanguage) {
}
@Override
public void languageRemoved(SModule sModule, SLanguage sLanguage) {
}
@Override
public void moduleChanged(SModule sModule) {
}
private void packRunnable(final Runnable runnable) {
// the following mess is explained by this:
// 1. we're most likely in MPS reload session, which calls MPS write action which is in intellij's read action
// 2. to do notify psi change we need intellij write action
// 3. we can't just call write action because we're already in read
// 4. we also need mps read action because we read models (you might think about 1. but that mps write action was in another thread)
final Application app = ApplicationManager.getApplication();
app.invokeLater(new Runnable() {
@Override
public void run() {
app.runWriteAction(new Runnable() {
@Override
public void run() {
ProjectHelper.getModelAccess(myProject).runReadAction(runnable);
}
});
}
});
}
}