package jetbrains.mps.checkers; /*Generated by MPS */ import org.jetbrains.mps.openapi.language.SConcept; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import org.jetbrains.mps.openapi.language.SContainmentLink; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.module.SRepository; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import java.util.Set; import org.jetbrains.mps.openapi.language.SLanguage; import java.util.HashSet; import jetbrains.mps.smodel.SLanguageHierarchy; import jetbrains.mps.smodel.SModelOperations; import java.util.Collections; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.errors.messageTargets.NodeMessageTarget; import jetbrains.mps.errors.QuickFixProvider; import jetbrains.mps.errors.QuickFix_Runtime; import jetbrains.mps.smodel.SModelInternal; public class UsedLanguagesChecker extends AbstractNodeChecker { private final SConcept C = MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0xad0053c7ae9194dL, "jetbrains.mps.lang.core.structure.SideTransformInfo"); private final SContainmentLink L = MetaAdapterFactory.getContainmentLink(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, 0x47bf8397520e5942L, "smodelAttribute"); public UsedLanguagesChecker() { } public void checkNode(SNode node, LanguageErrorsCollector errorsCollector, SRepository repository) { if (SNodeOperations.getParent(node) != null) { return; } final Set<SLanguage> importedLanguages = new HashSet<SLanguage>(); importedLanguages.addAll(new SLanguageHierarchy(SModelOperations.getAllLanguageImports(SNodeOperations.getModel(node))).getExtended()); // need to recurse the tree, to report missing language once per sub-tree // (starting from the first node with missing language encountered) // Iterative alternative would be more complicated, and there are no utility // methods in the rules nor we support inner classes, hence the trick with Runnable findMissing(errorsCollector, Collections.singleton(node), Collections.<SLanguage>emptySet(), importedLanguages); } public void findMissing(LanguageErrorsCollector component, Iterable<? extends SNode> level, Set<SLanguage> parentReported, Set<SLanguage> imported) { boolean parentReportedSetChanged = false; for (SNode node : Sequence.fromIterable(level)) { HashSet<SLanguage> reported = new HashSet<SLanguage>(parentReported); SConcept concept = node.getConcept(); if (concept.equals(C) && L.equals(node.getContainmentLink())) { continue; } SLanguage language = concept.getLanguage(); boolean notYetReported = reported.add(language); parentReportedSetChanged |= notYetReported; if (!(imported.contains(language)) && notYetReported) { component.addError(node, language.getQualifiedName() + " is not imported", null, new NodeMessageTarget(), new UsedLanguagesChecker.LangImportQFixProvider()); } findMissing(component, node.getChildren(), (parentReportedSetChanged ? reported : parentReported), imported); } } private class LangImportQFixProvider implements QuickFixProvider { public LangImportQFixProvider() { } public QuickFix_Runtime getQuickFix() { return new QuickFix_Runtime() { @Override public String getDescription(SNode node) { return "Import " + node.getConcept().getLanguage().getQualifiedName() + " language"; } public void execute(SNode node) { SLanguage language = node.getConcept().getLanguage(); ((SModelInternal) node.getModel()).addLanguage(language); } }; } public boolean isExecutedImmediately() { return false; } public void setIsError(boolean val) { } public boolean isError() { return true; } } }