/* * Copyright 2003-2012 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.newTypesystem.context.typechecking; import gnu.trove.THashSet; import jetbrains.mps.errors.IErrorReporter; import jetbrains.mps.lang.smodel.generator.smodelAdapter.AttributeOperations; import jetbrains.mps.lang.typesystem.runtime.IsApplicableStatus; import jetbrains.mps.lang.typesystem.runtime.SubstituteType_Runtime; import jetbrains.mps.newTypesystem.context.component.SimpleTypecheckingComponent; import jetbrains.mps.newTypesystem.state.State; import jetbrains.mps.smodel.IOperationContext; import jetbrains.mps.typesystem.inference.TypeSubstitution; import jetbrains.mps.util.Cancellable; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.typesystem.inference.TypeCheckingContext; import jetbrains.mps.util.Pair; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; /** * User: fyodor * Date: 11/12/12 */ public abstract class BaseTypechecking<STATE extends State, COMP extends SimpleTypecheckingComponent> { protected final SNode myRootNode; private final STATE myState; private final COMP myTypecheckingComponent; public BaseTypechecking(SNode node, STATE state) { myRootNode = node; myState = state; myTypecheckingComponent = createTypecheckingComponent(); } protected STATE getState() { return myState; } @SuppressWarnings("unchecked") protected COMP createTypecheckingComponent() { return (COMP) new SimpleTypecheckingComponent<STATE>(getState(), this); } public SNode getNode() { return myRootNode; } public COMP getTypecheckingComponent() { return myTypecheckingComponent; } protected SNode computeTypesForNode_special(SNode initialNode, Collection<SNode> givenAdditionalNodes) { SNode result = getTypecheckingComponent().computeTypesForNode_special(initialNode, givenAdditionalNodes); return result; } public SNode computeTypesForNodeDuringGeneration(SNode initialNode) { return computeTypesForNode_special(initialNode, Collections.<SNode>emptyList()); } public SNode computeTypesForNodeDuringResolving(SNode initialNode) { return computeTypesForNode_special(initialNode, Collections.<SNode>emptyList()); } public SNode computeTypesForNodeInferenceMode(SNode initialNode) { return computeTypesForNode_special(initialNode, Collections.<SNode>emptyList()); } @NotNull public List<IErrorReporter> getErrors(SNode node) { Map<SNode, List<IErrorReporter>> nodesToErrorsMap = getTypecheckingComponent().getNodesToErrorsMap(); List<IErrorReporter> result = new ArrayList<IErrorReporter>(4); List<IErrorReporter> iErrorReporters = nodesToErrorsMap.get(node); if (iErrorReporters != null) { result.addAll(iErrorReporters); } return result; } public void addNodeToFrontier(SNode node) { getTypecheckingComponent().addNodeToFrontier(node); } public void dispose() { } public void computeTypes(boolean refreshTypes) { getTypecheckingComponent().computeTypes(refreshTypes); } public void setCheckedTypesystem() { getTypecheckingComponent().setChecked(); } public Set<Pair<SNode, List<IErrorReporter>>> getNodesWithErrors(boolean typesystemErrors) { Map<SNode, List<IErrorReporter>> nodesToErrorsMap = getTypecheckingComponent().getNodesToErrorsMap(); Set<SNode> keySet = new THashSet<SNode>(nodesToErrorsMap.keySet()); Set<Pair<SNode, List<IErrorReporter>>> result = new THashSet<Pair<SNode, List<IErrorReporter>>>(1); for (SNode key : keySet) { List<IErrorReporter> reporters = nodesToErrorsMap.get(key); if (!reporters.isEmpty()) { if (key.getContainingRoot() == null) { /* LOG.warn("Type system reports error for node without containing root. Node: " + key); for (IErrorReporter reporter : reporters) { LOG.warn("This error was reported from: model: " + reporter.getRuleModel() + " id: " + reporter.getRuleId()); } */ continue; } result.add(new Pair<SNode, List<IErrorReporter>>(key, reporters)); } } return result; } public boolean isChecked(boolean considerNonTypeSystemRules) { return getTypecheckingComponent().isChecked(); } public void applyNonTypesystemRulesToRoot(TypeCheckingContext typeCheckingContext) { applyNonTypesystemRulesToRoot(typeCheckingContext, Cancellable.NEVER); } /** * Should return true iff the operation has succeeded and was not cancelled. */ public abstract boolean applyNonTypesystemRulesToRoot(TypeCheckingContext typeCheckingContext, Cancellable c); /** * Returns the list of all node attributes with the attributedNode added as the last. * The rules applicable to earlier attributes can be amended by the rules applicable to attributes added later. * At some point a rule may declare to "supercede" the rules that follow, which then become obsolete. * This logic is in sync with the editor's policy for overriding editor cells using attributes. * @param attributedNode */ public List<SNode> nodesToApplyRulesTo(SNode attributedNode) { if (attributedNode == null) return Collections.emptyList(); ArrayList<SNode> nodesToTest = new ArrayList<SNode>(AttributeOperations.getAllAttributes(attributedNode)); nodesToTest.add(attributedNode); return nodesToTest; } }