/******************************************************************************* * Copyright (c) 2014 Bruno Medeiros and other Contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package mmrnmhrm.core.engine; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import java.io.IOException; import dtool.engine.ModuleParseCache; import dtool.engine.ModuleParseCache.CachedModuleEntry; import dtool.engine.SemanticManager; import dtool.parser.DeeParserResult.ParsedModule; import dtool.parser.structure.DeeStructureCreator; import melnorme.lang.ide.core.engine.SourceModelManager; import melnorme.lang.tooling.structure.SourceFileStructure; import melnorme.utilbox.concurrency.OperationCancellation; import melnorme.utilbox.misc.Location; public class DeeSourceModelManager extends SourceModelManager { protected final DeeLanguageEngine languageEngine; public DeeSourceModelManager() { this(DeeLanguageEngine.getDefault()); } public DeeSourceModelManager(DeeLanguageEngine languageEngine) { super(); this.languageEngine = assertNotNull(languageEngine); } public SemanticManager getServerSemanticManager() { return languageEngine.dtoolServer.getSemanticManager(); } protected ModuleParseCache getParseCache() { return getServerSemanticManager().getParseCache(); } /* ----------------- ----------------- */ public abstract class WorkingCopyStructureUpdateTask extends StructureUpdateTask { protected final Location fileLocation; // can be null public WorkingCopyStructureUpdateTask(StructureInfo structureInfo) { super(structureInfo); this.fileLocation = structureInfo.getLocation(); } @Override protected SourceFileStructure doCreateNewData() throws OperationCancellation { ParsedModule parsedModule = (fileLocation == null) ? parseModuleWithNoLocation() : setWorkingSourceAndParseModule(fileLocation); if(parsedModule == null || isCancelled()) { throw new OperationCancellation(); } return new DeeStructureCreator().createStructure(parsedModule, fileLocation); } /** * @param fileLocation non-null */ protected ParsedModule setWorkingSourceAndParseModule(Location fileLocation) { final CachedModuleEntry entry = getParseCache().getEntry(fileLocation.toPath()); entry.runUnderEntryLock(new Runnable() { @Override public void run() { if(!isCancelled()) { modifyWorkingSource(entry); } } }); if(isCancelled()) { return null; } try { return parseModuleFromWorkingCopy(entry); } catch(OperationCancellation e) { return null; } } protected abstract ParsedModule parseModuleWithNoLocation(); protected abstract void modifyWorkingSource(CachedModuleEntry lockedEntry); protected abstract ParsedModule parseModuleFromWorkingCopy(CachedModuleEntry entry) throws OperationCancellation; } @Override protected StructureUpdateTask createUpdateTask(StructureInfo structureInfo, String source) { assertNotNull(source); return new WorkingCopyStructureUpdateTask(structureInfo) { @Override protected ParsedModule parseModuleWithNoLocation() { try { return getParseCache().parseModuleWithNoLocation(source, cm); } catch(OperationCancellation e) { return null; } } @Override protected void modifyWorkingSource(CachedModuleEntry lockedEntry) { lockedEntry.setWorkingSource(source); } @Override protected ParsedModule parseModuleFromWorkingCopy(CachedModuleEntry entry) throws OperationCancellation { try { return entry.getParsedModule(cm); } catch(IOException e) { return null; } } }; } @Override protected DisconnectUpdatesTask createDisconnectTask(StructureInfo structureInfo) { return new DisconnectUpdatesTask(structureInfo) { @Override protected void handleDisconnectForLocation(Location location) { getParseCache().discardWorkingCopy(location.toPath()); } }; } }