package org.absmodels.abs.plugin.editor.reconciling;
import static org.absmodels.abs.plugin.util.Constants.DEFAULT_LOCATION_TYPE;
import static org.absmodels.abs.plugin.util.Constants.LOCATION_TYPECHECK;
import static org.absmodels.abs.plugin.util.Constants.LOCATION_TYPE_PRECISION;
import java.util.ArrayList;
import java.util.List;
import org.absmodels.abs.plugin.Activator;
import org.absmodels.abs.plugin.builder.AbsNature;
import org.absmodels.abs.plugin.internal.IncrementalModelBuilder;
import org.absmodels.abs.plugin.util.Constants;
import org.absmodels.abs.plugin.util.CoreControlUnit;
import org.absmodels.abs.plugin.util.CoreControlUnit.ResourceBuildListener;
import org.absmodels.abs.plugin.util.CoreControlUnit.ResourceBuiltEvent;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.preference.IPersistentPreferenceStore;
import abs.frontend.analyser.SemanticConditionList;
import abs.frontend.ast.CompilationUnit;
import abs.frontend.ast.Model;
import abs.frontend.parser.Main;
import abs.frontend.typechecker.locationtypes.LocationType;
import abs.frontend.typechecker.locationtypes.infer.LocationTypeInferrerExtension;
import abs.frontend.typechecker.locationtypes.infer.LocationTypeInferrerExtension.LocationTypingPrecision;
public class AbsModelManagerImpl implements AbsModelManager, ResourceBuildListener {
private AbsNature absNature;
private Model model;
private List<ModelChangeListener> changeListeners = new ArrayList<ModelChangeListener>();
public AbsModelManagerImpl(AbsNature absNature) {
this.absNature = absNature;
CoreControlUnit.addResourceBuildListener(this);
updateModelFromNature();
}
@Override
public synchronized void updateModel(CompilationUnit cu, boolean withTypechecks) {
boolean added = false;
for (int i=0; i<model.getNumCompilationUnit(); i++) {
CompilationUnit c = model.getCompilationUnit(i);
if (c.getFileName().equals(cu.getFileName())) {
// update compilation unit:
model.setCompilationUnit(cu, i);
added = true;
break;
}
}
if (!added) {
model.addCompilationUnit(cu);
}
Main.exceptionHack(model);
if (!model.hasParserErrors()) {
if (withTypechecks) {
extendedTypechecking();
}
}
notifyChangeListeners();
}
private void notifyChangeListeners() {
for (ModelChangeListener cl : changeListeners) {
cl.onModelChange(model);
}
}
private void extendedTypechecking() {
if (absNature.getProject() != null) {
IPersistentPreferenceStore projectPreferences = absNature.getProjectPreferenceStore();
IncrementalModelBuilder.flushAll(model);
model.getTypeExt().clearTypeSystemExtensions();
boolean dolocationtypecheck = projectPreferences.getBoolean(LOCATION_TYPECHECK);
if (dolocationtypecheck) {
String defaultlocationtypeprecision = projectPreferences.getString(LOCATION_TYPE_PRECISION);
LocationType defaultLocType = LocationType.createFromName(projectPreferences.getString(DEFAULT_LOCATION_TYPE));
LocationTypeInferrerExtension ltie = new LocationTypeInferrerExtension(model);
ltie.setDefaultType(defaultLocType);
ltie.setLocationTypingPrecision(LocationTypingPrecision.valueOf(defaultlocationtypeprecision));
model.registerTypeSystemExtension(ltie);
}
}
Main.exceptionHack(model);
SemanticConditionList typeErrors = model.typeCheck();
updateMarkers(typeErrors);
}
private void updateMarkers(SemanticConditionList typeErrors) {
// update markers
try {
if (absNature.getProject() == null) {
return;
}
absNature.getProject().deleteMarkers(Constants.TYPECHECK_MARKER_TYPE, true, IResource.DEPTH_INFINITE);
absNature.createMarkers(typeErrors);
} catch (CoreException e) {
Activator.logException(e);
}
}
@Override
public synchronized Model getModel() {
return model;
}
@Override
public synchronized CompilationUnit getCompilationUnit(String absoluteFilePath) {
if (model == null) {
/* Project hasn't been built yet. */
try {
absNature.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
} catch (CoreException e) {
Activator.logException(e);
return null;
}
updateModelFromNature();
}
assert model != null;
for (CompilationUnit cu : model.getCompilationUnits()) {
if (cu.getFileName().equals(absoluteFilePath)) {
return cu;
}
}
return null;
}
@Override
public synchronized void resourceBuilt(ResourceBuiltEvent builtevent) {
updateModelFromNature();
}
private void updateModelFromNature() {
Model build = absNature.getCompleteModel();
if (build != null && model != build) {
model = build.parseTreeCopy();
// XXX Check if parseTreeCopy does the right thing.
Main.exceptionHack(model);
notifyChangeListeners();
}
}
}