package jetbrains.mps.checkers; /*Generated by MPS */ import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.module.SRepository; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import org.jetbrains.mps.openapi.module.SModule; import jetbrains.mps.resolve.ReferenceResolverUtils; import org.jetbrains.mps.openapi.model.SReference; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import jetbrains.mps.smodel.constraints.ReferenceDescriptor; import jetbrains.mps.smodel.constraints.ModelConstraints; import jetbrains.mps.scope.Scope; import jetbrains.mps.scope.ErrorScope; import jetbrains.mps.errors.messageTargets.ReferenceMessageTarget; import jetbrains.mps.smodel.runtime.ReferenceScopeProvider; import org.jetbrains.mps.openapi.model.SNodeReference; import jetbrains.mps.errors.QuickFixProvider; import jetbrains.mps.errors.QuickFix_Runtime; import jetbrains.mps.resolve.ResolverComponent; public class RefScopeChecker extends AbstractNodeChecker { public RefScopeChecker() { } @Override public void checkNode(SNode node, LanguageErrorsCollector errorsCollector, SRepository repository) { if (node == null || SNodeOperations.getModel(node) == null) { return; } SModule module = SNodeOperations.getModel(node).getModule(); if (module == null) { return; } boolean executeImmediately = ReferenceResolverUtils.canExecuteImmediately(SNodeOperations.getModel(node), repository); for (SReference ref : SNodeOperations.getReferences(node)) { SNode target = SLinkOperations.getTargetNode(ref); if (target == null) { continue; } // don't check unresolved and broken references, they should already have an error message // do we need all these additional dependencies? mb. it's better to use .runcheckingAction() instead? errorsCollector.addDependency(target); errorsCollector.addDependency(SNodeOperations.getParent(node)); for (SNode c : SNodeOperations.getChildren(node)) { errorsCollector.addDependency(c); } ReferenceDescriptor refDescriptor = ModelConstraints.getReferenceDescriptor(ref); Scope refScope = refDescriptor.getScope(); if (refScope instanceof ErrorScope) { errorsCollector.addError(node, ((ErrorScope) refScope).getMessage(), null, new ReferenceMessageTarget(SLinkOperations.getRefLink(ref).getName())); } else if (!(refScope.contains(target))) { String name = target.getName(); ReferenceScopeProvider scopeProvider = refDescriptor.getScopeProvider(); SNodeReference ruleNode = null; if (scopeProvider != null) { ruleNode = scopeProvider.getSearchScopeValidatorNode(); } errorsCollector.addError(node, "reference" + ((name == null ? "" : " " + name)) + " (" + SLinkOperations.getRefLink(ref).getName() + ") is out of search scope", ruleNode, new ReferenceMessageTarget(SLinkOperations.getRefLink(ref).getName()), createResolveReferenceQuickfix(ref, repository, executeImmediately)); } } } protected QuickFixProvider createResolveReferenceQuickfix(SReference reference, SRepository repository, boolean executeImmediately) { return new RefScopeChecker.ResolveReferenceQuickFix(reference, repository, executeImmediately); } protected class ResolveReferenceQuickFix implements QuickFixProvider { private boolean myIsError; protected SReference myReference; protected SRepository myRepository; private boolean myExecuteImmediately; public ResolveReferenceQuickFix(SReference reference, SRepository repository, boolean executeImmediately) { myReference = reference; myRepository = repository; myExecuteImmediately = executeImmediately; } @Override public QuickFix_Runtime getQuickFix() { return new QuickFix_Runtime() { @Override public void execute(SNode node) { ResolverComponent.getInstance().resolve(myReference, myRepository); } @Override public String getDescription(SNode node) { return "Resolve \"" + myReference.getLink().getName() + "\" reference"; } }; } @Override public boolean isExecutedImmediately() { return myExecuteImmediately; } @Override public void setIsError(boolean isError) { myIsError = isError; } @Override public boolean isError() { return myIsError; } } }