package jetbrains.mps.ide.java.platform.highlighters.methodcallsfixer;
/*Generated by MPS */
import jetbrains.mps.nodeEditor.checking.BaseEditorChecker;
import org.jetbrains.mps.openapi.module.SRepository;
import java.util.List;
import jetbrains.mps.smodel.event.SModelEvent;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.smodel.event.SModelReplacedEvent;
import jetbrains.mps.nodeEditor.EditorComponent;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.nodeEditor.checking.UpdateResult;
import jetbrains.mps.util.Cancellable;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.typesystem.inference.TypeContextManager;
import jetbrains.mps.typesystem.inference.ITypechecking;
import jetbrains.mps.typesystem.inference.TypeCheckingContext;
import java.util.Collections;
import jetbrains.mps.nodeEditor.EditorMessage;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import org.jetbrains.mps.openapi.model.EditableSModel;
import jetbrains.mps.extapi.module.TransientSModule;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SAbstractConcept;
import java.util.Map;
import jetbrains.mps.ide.ThreadUtils;
import org.jetbrains.mps.openapi.model.SNodeUtil;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
public class MethodCallsFixer extends BaseEditorChecker {
private static boolean DISABLED = false;
private final SRepository myRepository;
private MethodCallsUpdateSession myCurrentSession;
public MethodCallsFixer(SRepository repository) {
myRepository = repository;
}
@Override
public void processEvents(final List<SModelEvent> events) {
if (myCurrentSession == null) {
return;
}
final UpdateSessionEventVisitor visitor = new UpdateSessionEventVisitor(myCurrentSession);
// Start a read action here since MethodDeclarationFixer used to process events in a read action.
// Ideally we should not need read action and we should avoid walking through the model since we receive events
// asynchronously and with a delay, so the model may be in an unexpected state.
myRepository.getModelAccess().runReadAction(new Runnable() {
public void run() {
for (SModelEvent event : ListSequence.fromList(events)) {
if (event instanceof SModelReplacedEvent) {
myCurrentSession = null;
break;
}
event.accept(visitor);
}
}
});
}
@Override
public boolean needsUpdate(EditorComponent component) {
return myCurrentSession == null || myCurrentSession.hasMethodCallsToUpdate();
}
@NotNull
@Override
public UpdateResult update(EditorComponent editorComponent, final boolean incremental, boolean applyQuickFixes, Cancellable cancellable) {
try {
final SRepository repository = editorComponent.getEditorContext().getRepository();
final SNode editedNode = editorComponent.getEditedNode();
if (editedNode == null) {
return UpdateResult.CANCELLED;
}
TypeContextManager.getInstance().runTypeCheckingAction(editorComponent.getTypecheckingContextOwner(), editedNode, new ITypechecking.Action() {
@Override
public void run(TypeCheckingContext context) {
doCreateMessages(editedNode, incremental, repository);
}
});
return new UpdateResult.Completed(true, Collections.<EditorMessage>emptySet());
} catch (RuntimeException e) {
myCurrentSession = null;
throw e;
}
}
private void doCreateMessages(SNode rootNode, boolean incremental, final SRepository repository) {
if (DISABLED) {
return;
}
SModel model = SNodeOperations.getModel(rootNode);
if (!(model instanceof EditableSModel) || model.getModule() instanceof TransientSModule || jetbrains.mps.util.SNodeOperations.isModelDisposed(model)) {
return;
}
if (!(incremental)) {
myCurrentSession = null;
}
if (myCurrentSession == null) {
myCurrentSession = new MethodCallsUpdateSession(myRepository);
incremental = false;
}
if (!(incremental)) {
for (SNode methodCall : SNodeOperations.getNodeDescendants(rootNode, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, "jetbrains.mps.baseLanguage.structure.IMethodCall"), false, new SAbstractConcept[]{})) {
myCurrentSession.checkMethodCall(methodCall);
}
}
final Map<SNode, SNode> methodCallsToUpdate = myCurrentSession.collectMethodCallsToUpdate();
if (!(methodCallsToUpdate.isEmpty()) && repository != null) {
ThreadUtils.runInUIThreadNoWait(new Runnable() {
public void run() {
repository.getModelAccess().executeUndoTransparentCommand(new Runnable() {
public void run() {
for (SNode methodCall : methodCallsToUpdate.keySet()) {
SNode referent = methodCallsToUpdate.get(methodCall);
if (referent != null && SNodeUtil.isAccessible(referent, repository)) {
SLinkOperations.setTarget(methodCall, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, 0xf8c78301adL, "baseMethodDeclaration"), referent);
}
}
}
});
}
});
}
}
}