/*
* Copyright 2003-2011 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.component;
import gnu.trove.THashSet;
import jetbrains.mps.newTypesystem.context.typechecking.BaseTypechecking;
import jetbrains.mps.newTypesystem.state.State;
import jetbrains.mps.smodel.AbstractNodesReadListener;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.typesystem.inference.TypeChecker;
import jetbrains.mps.util.Pair;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
/*package*/ public abstract class IncrementalTypecheckingComponent<STATE extends State> extends SimpleTypecheckingComponent<STATE> {
private AtomicBoolean myInvalidationWasPerformed = new AtomicBoolean(false);
private AtomicBoolean myCacheWasRebuilt = new AtomicBoolean(false);
private AtomicBoolean myInvalidationResult = new AtomicBoolean(false);
private Set<SNode> myCurrentNodesToInvalidate = new THashSet<SNode>();
protected IncrementalTypecheckingComponent(TypeChecker typeChecker, STATE state, BaseTypechecking component) {
super(state, component);
}
@Override
protected abstract boolean doInvalidate();
public void setInvalidationWasPerformed(boolean invalidationWasPerformed) {
myInvalidationWasPerformed.set(invalidationWasPerformed);
}
public void addNodeToInvalidate(SNode node) {
myCurrentNodesToInvalidate.add(node);
setInvalidationWasPerformed(false);
}
@Override
public void clear() {
myIsChecked = false;
myInvalidationWasPerformed.set(false);
myCacheWasRebuilt.set(false);
myInvalidationResult.set(false);
}
public void clearNodeTypes() {
myCurrentNodesToInvalidate.clear();
}
protected boolean isInvalidationWasPerformed() {
return myInvalidationWasPerformed.get();
}
protected boolean isCacheWasRebuilt() {
return myCacheWasRebuilt.get();
}
protected boolean isInvalidationResult() {
return myInvalidationResult.get();
}
protected Set<SNode> getCurrentNodesToInvalidate() {
return new THashSet<SNode>(myCurrentNodesToInvalidate);
}
/*
* Single-threaded
*/
protected class MyEventsReadListener extends AbstractNodesReadListener {
private Set<SNode> myAccessedNodes = new THashSet<SNode>(1);
private Set<Pair<SNode, String>> myAccessedProperties = new THashSet<Pair<SNode, String>>(1);
private boolean myIsSetAccessReport = false;
public MyEventsReadListener() {
}
public void setAccessReport(boolean accessReport) {
myIsSetAccessReport = accessReport;
}
private void reportAccess() {
if (myIsSetAccessReport) {
new Throwable().printStackTrace();
}
}
@Override
public void nodeChildReadAccess(SNode node, String childRole, SNode child) {
reportAccess();
myAccessedNodes.add(node);
if (child != null) {
myAccessedNodes.add(child);
}
}
@Override
public void nodePropertyReadAccess(SNode node, String propertyName, String value) {
reportAccess();
myAccessedProperties.add(new Pair<SNode, String>(node, propertyName));
}
@Override
public void nodeReferentReadAccess(SNode node, String referentRole, SNode referent) {
reportAccess();
myAccessedNodes.add(node);
if (referent != null) {
myAccessedNodes.add(referent);
}
}
@Override
public void nodeUnclassifiedReadAccess(SNode node) {
reportAccess();
myAccessedNodes.add(node);
}
public Set<SNode> getAccessedNodes() {
return myAccessedNodes;
}
public void clear() {
reportAccess();
myAccessedNodes = new THashSet<SNode>();
myAccessedProperties = new THashSet<Pair<SNode, String>>();
}
public Set<Pair<SNode, String>> getAccessedProperties() {
return myAccessedProperties;
}
}
protected void setInvalidationResult(boolean result) {
setInvalidationWasPerformed(true);
myCacheWasRebuilt.set(false);
myInvalidationResult.set(result);
}
}