Commit af1c2e03 authored by Johannes Roith's avatar Johannes Roith

- Fixed memory leaks.

- All observers now unregister properly at the controller and model.
- Some other minor changes.
parent 15f3f474
...@@ -26,11 +26,9 @@ public class Controller { ...@@ -26,11 +26,9 @@ public class Controller {
private static final int SET_CHANGED_AFTER_SECONDS = 1; private static final int SET_CHANGED_AFTER_SECONDS = 1;
// TODO: we need to remove the editor from the list, when it gets disposed.
private static WeakHashMap<CupTextEditor, Controller> instances = new WeakHashMap<CupTextEditor, Controller>(); private static WeakHashMap<CupTextEditor, Controller> instances = new WeakHashMap<CupTextEditor, Controller>();
// The Job that's executed after a document change is detected (changeJob)
private DocumentDidChangeJob myJob = null; private DocumentDidChangeJob job = null;
// if the changeJob takes some time, it's good to know if it has to be // if the changeJob takes some time, it's good to know if it has to be
// reexecuted after it finishes // reexecuted after it finishes
...@@ -45,6 +43,11 @@ public class Controller { ...@@ -45,6 +43,11 @@ public class Controller {
private Set<IRegisterForControllerChanges> controllerObservers = Collections private Set<IRegisterForControllerChanges> controllerObservers = Collections
.newSetFromMap(new WeakHashMap<IRegisterForControllerChanges, Boolean>()); .newSetFromMap(new WeakHashMap<IRegisterForControllerChanges, Boolean>());
public static void deleteForEditor(CupTextEditor editor) {
if (instances.containsKey(editor))
instances.remove(editor);
}
public static Controller getInstance(CupTextEditor edit) { public static Controller getInstance(CupTextEditor edit) {
Controller instance = instances.get(edit); Controller instance = instances.get(edit);
if (instance != null) { if (instance != null) {
...@@ -57,8 +60,8 @@ public class Controller { ...@@ -57,8 +60,8 @@ public class Controller {
private Controller(CupTextEditor editor) { private Controller(CupTextEditor editor) {
this.editor = editor; this.editor = editor;
myJob = new DocumentDidChangeJob(editor); job = new DocumentDidChangeJob(editor);
myJob.setSystem(true); job.setSystem(true);
documentEvents = new LinkedList<DocumentEvent>(); documentEvents = new LinkedList<DocumentEvent>();
Debugger.getInstance(editor.getDocument()); // TODO: why is this here? Debugger.getInstance(editor.getDocument()); // TODO: why is this here?
} }
...@@ -102,7 +105,7 @@ public class Controller { ...@@ -102,7 +105,7 @@ public class Controller {
public void initialRun() { public void initialRun() {
addJobToDo(JobsToDo.parseCode); addJobToDo(JobsToDo.parseCode);
addJobToDo(JobsToDo.buildTable); addJobToDo(JobsToDo.buildTable);
myJob.schedule(0); job.schedule(0);
} }
public void registerObserver(IRegisterForControllerChanges observer) { public void registerObserver(IRegisterForControllerChanges observer) {
...@@ -215,13 +218,13 @@ public class Controller { ...@@ -215,13 +218,13 @@ public class Controller {
} }
private void runJobs(IDocument document) { private void runJobs(IDocument document) {
if (myJob.getState() == Job.NONE if (job.getState() == Job.NONE
|| (!myJob.running() && myJob.getState() == Job.SLEEPING)) { || (!job.running() && job.getState() == Job.SLEEPING)) {
myJob.cancel(); job.cancel();
myJob.revNumber = RevisionManager.increment(document); job.revNumber = RevisionManager.increment(document);
myJob.schedule(SET_CHANGED_AFTER_SECONDS * 1000); job.schedule(SET_CHANGED_AFTER_SECONDS * 1000);
} else { } else {
RevisionManager.increment(document); RevisionManager.increment(document);
changeJobReRunRequested = System.currentTimeMillis(); changeJobReRunRequested = System.currentTimeMillis();
...@@ -279,10 +282,6 @@ public class Controller { ...@@ -279,10 +282,6 @@ public class Controller {
*/ */
public void notifyChangeJobFinished() { public void notifyChangeJobFinished() {
synchronized (lock) { synchronized (lock) {
/*
* System.out.println("job finished -> " + changeJobReRunRequested);
* TODO: REMOVE OUTPUT
*/
if (changeJobReRunRequested > 0) { if (changeJobReRunRequested > 0) {
changeJobReRunRequested = 0; changeJobReRunRequested = 0;
...@@ -290,8 +289,8 @@ public class Controller { ...@@ -290,8 +289,8 @@ public class Controller {
// ??? // ???
long remainderOfDelay = (SET_CHANGED_AFTER_SECONDS * 100) long remainderOfDelay = (SET_CHANGED_AFTER_SECONDS * 100)
- (System.currentTimeMillis() - changeJobReRunRequested); - (System.currentTimeMillis() - changeJobReRunRequested);
myJob.revNumber = RevisionManager.get(editor.getDocument()); job.revNumber = RevisionManager.get(editor.getDocument());
myJob.schedule((remainderOfDelay >= 0) ? remainderOfDelay : 0); job.schedule((remainderOfDelay >= 0) ? remainderOfDelay : 0);
} }
} }
} }
......
...@@ -133,12 +133,12 @@ public class DocumentDidChangeJob extends Job { ...@@ -133,12 +133,12 @@ public class DocumentDidChangeJob extends Job {
e.printStackTrace(); e.printStackTrace();
} }
} else { } else {
if (context != null) {
StatisticsIfFailedJob statisticsJob = new StatisticsIfFailedJob( StatisticsIfFailedJob statisticsJob = new StatisticsIfFailedJob(
editor, context, revNumber); editor, context, revNumber);
statisticsJob.setSystem(true); statisticsJob.setSystem(true);
statisticsJob.schedule(); statisticsJob.schedule();
}
jobStatusList.add(new JobStatus(JobsToDo.parseCode, true)); jobStatusList.add(new JobStatus(JobsToDo.parseCode, true));
//return Status.CANCEL_STATUS; //return Status.CANCEL_STATUS;
} }
...@@ -180,12 +180,12 @@ public class DocumentDidChangeJob extends Job { ...@@ -180,12 +180,12 @@ public class DocumentDidChangeJob extends Job {
// TODO: we run the statistics job twice, here, even if we failed // TODO: we run the statistics job twice, here, even if we failed
// to build the parser. This should only run once. // to build the parser. This should only run once.
if (context != null) {
StatisticsIfFailedJob statisticsJob = new StatisticsIfFailedJob( StatisticsIfFailedJob statisticsJob = new StatisticsIfFailedJob(
editor, context, revNumber); editor, context, revNumber);
statisticsJob.setSystem(true); statisticsJob.setSystem(true);
statisticsJob.schedule(); statisticsJob.schedule();
}
jobStatusList.add(new JobStatus(JobsToDo.buildTable, true)); jobStatusList.add(new JobStatus(JobsToDo.buildTable, true));
} }
} }
...@@ -236,6 +236,7 @@ public class DocumentDidChangeJob extends Job { ...@@ -236,6 +236,7 @@ public class DocumentDidChangeJob extends Job {
@Override @Override
public IStatus runInUIThread(IProgressMonitor monitor) { public IStatus runInUIThread(IProgressMonitor monitor) {
Controller controller = Controller.getInstance(editor); Controller controller = Controller.getInstance(editor);
if (documentDidChangeJob.documentEvents == null if (documentDidChangeJob.documentEvents == null
...@@ -253,11 +254,11 @@ public class DocumentDidChangeJob extends Job { ...@@ -253,11 +254,11 @@ public class DocumentDidChangeJob extends Job {
documentDidChangeJob.jobs.addAll(controller.popJobsToDo()); documentDidChangeJob.jobs.addAll(controller.popJobsToDo());
} }
jobStatusList.clear(); jobStatusList.clear();
if (editor == null)
return Status.CANCEL_STATUS;
IDocument document = editor.getDocument(); if (editor == null || editor.hasBeenDisposed())
return Status.CANCEL_STATUS;
IDocument document = editor.getDocument();
if (revNumber != RevisionManager.get(document)) if (revNumber != RevisionManager.get(document))
return Status.CANCEL_STATUS; return Status.CANCEL_STATUS;
......
...@@ -12,12 +12,15 @@ import org.eclipse.jface.text.contentassist.ICompletionProposal; ...@@ -12,12 +12,15 @@ import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator; import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import de.in.tum.www2.cup.Declarations; import de.in.tum.www2.cup.Declarations;
import de.in.tum.www2.cup.ast.ParserResult; import de.in.tum.www2.cup.ast.ParserResult;
import de.tum.in.www2.cupplugin.IDisposable;
import de.tum.in.www2.cupplugin.controller.Controller;
import de.tum.in.www2.cupplugin.model.*; import de.tum.in.www2.cupplugin.model.*;
public class CupContentAssistProcessor implements IContentAssistProcessor, public class CupContentAssistProcessor implements IContentAssistProcessor,
ICupParserASTChangeObserver { IDisposable, ICupParserASTChangeObserver {
private Declarations decls; private Declarations decls;
private IDocument doc; private IDocument doc;
...@@ -29,10 +32,10 @@ public class CupContentAssistProcessor implements IContentAssistProcessor, ...@@ -29,10 +32,10 @@ public class CupContentAssistProcessor implements IContentAssistProcessor,
Model model = Model.getInstanceForDocument(doc); Model model = Model.getInstanceForDocument(doc);
updateFromParserResult(model.getAstModel()); updateFromParserResult(model.getAstModel());
model.registerModelObserver(this); model.registerModelObserver(this);
}
public void dispose() {
// TODO: de-register on dispose! Model.getInstanceForDocument(doc).unregisterModelObserver(this);
} }
private void updateFromParserResult(ParserResult result) { private void updateFromParserResult(ParserResult result) {
......
...@@ -6,7 +6,6 @@ import java.util.List; ...@@ -6,7 +6,6 @@ import java.util.List;
import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IFontProvider; import org.eclipse.jface.viewers.IFontProvider;
...@@ -64,8 +63,8 @@ public class CupContentOutlinePage extends ContentOutlinePage implements ...@@ -64,8 +63,8 @@ public class CupContentOutlinePage extends ContentOutlinePage implements
@Override @Override
public void dispose() { public void dispose() {
System.out.println("DISPOSING OUTLINE OBSERVER!"); Model.getInstanceForDocument(doc).unregisterModelObserver(this);
Model.getInstanceForDocument(doc).deRegisterModelObserver(this); Controller.getInstance(editor).unregisterObserver(this);
super.dispose(); super.dispose();
}; };
......
...@@ -2,8 +2,11 @@ package de.tum.in.www2.cupplugin.editors; ...@@ -2,8 +2,11 @@ package de.tum.in.www2.cupplugin.editors;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set;
import java.util.WeakHashMap;
import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Shell;
import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadLocationException;
...@@ -42,8 +45,10 @@ import de.in.tum.www2.cup.ast.ParserResult; ...@@ -42,8 +45,10 @@ import de.in.tum.www2.cup.ast.ParserResult;
import de.in.tum.www2.cup.ast.ProductionRight; import de.in.tum.www2.cup.ast.ProductionRight;
import de.in.tum.www2.java.JavaScanner; import de.in.tum.www2.java.JavaScanner;
import de.in.tum.www2.java.JavaSymbol; import de.in.tum.www2.java.JavaSymbol;
import de.tum.in.www2.cupplugin.IDisposable;
import de.tum.in.www2.cupplugin.PluginUtility; import de.tum.in.www2.cupplugin.PluginUtility;
import de.tum.in.www2.cupplugin.controller.Controller.JobsToDo; import de.tum.in.www2.cupplugin.controller.Controller.JobsToDo;
import de.tum.in.www2.cupplugin.controller.Controller;
import de.tum.in.www2.cupplugin.controller.IRegisterForControllerChanges; import de.tum.in.www2.cupplugin.controller.IRegisterForControllerChanges;
import de.tum.in.www2.cupplugin.controller.JobStatus; import de.tum.in.www2.cupplugin.controller.JobStatus;
import de.tum.in.www2.cupplugin.model.ICupParserASTChangeObserver; import de.tum.in.www2.cupplugin.model.ICupParserASTChangeObserver;
...@@ -53,7 +58,11 @@ import de.tum.in.www2.cupplugin.syntax.JavaTokenScanner; ...@@ -53,7 +58,11 @@ import de.tum.in.www2.cupplugin.syntax.JavaTokenScanner;
import de.tum.in.www2.cupplugin.syntax.SingleTokenScanner; import de.tum.in.www2.cupplugin.syntax.SingleTokenScanner;
public class CupSourceViewerConfiguration extends SourceViewerConfiguration { public class CupSourceViewerConfiguration extends SourceViewerConfiguration {
CupTextEditor editor;
private CupTextEditor editor;
private Set<IDisposable> disposables = Collections
.newSetFromMap(new WeakHashMap<IDisposable, Boolean>());
private static final int AUTO_ACTIVATION_DELAY = 500; private static final int AUTO_ACTIVATION_DELAY = 500;
...@@ -61,6 +70,12 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration { ...@@ -61,6 +70,12 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration {
this.editor = editor; this.editor = editor;
} }
public void dispose() {
for (IDisposable d : disposables)
if (d != null)
d.dispose();
}
@Override @Override
public IHyperlinkPresenter getHyperlinkPresenter(ISourceViewer sourceViewer) { public IHyperlinkPresenter getHyperlinkPresenter(ISourceViewer sourceViewer) {
return new MultipleHyperlinkPresenter(CupTextEditor.HYPERLINK.getRGB()); return new MultipleHyperlinkPresenter(CupTextEditor.HYPERLINK.getRGB());
...@@ -74,21 +89,19 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration { ...@@ -74,21 +89,19 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration {
@Override @Override
public ITextHover getTextHover(ISourceViewer sourceViewer, public ITextHover getTextHover(ISourceViewer sourceViewer,
String contentType) { String contentType) {
return new CupTextHover(editor); CupTextHover cth = new CupTextHover(editor);
disposables.add(cth);
return cth;
} }
@Override @Override
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
IDocument doc = editor.getDocument();
CupContentAssistProcessor tcap = new CupContentAssistProcessor(doc);
disposables.add(tcap);
ContentAssistant assistant = new ContentAssistant(); ContentAssistant assistant = new ContentAssistant();
assistant.setContentAssistProcessor(tcap, IDocument.DEFAULT_CONTENT_TYPE);
// TODO: correct to get the doc like that?
IDocument doc = editor.getDocumentProvider().getDocument(
editor.getEditorInput());
IContentAssistProcessor tagContentAssistProcessor = new CupContentAssistProcessor(
doc);
assistant.setContentAssistProcessor(tagContentAssistProcessor,
IDocument.DEFAULT_CONTENT_TYPE);
assistant.enableAutoActivation(true); assistant.enableAutoActivation(true);
assistant.setAutoActivationDelay(AUTO_ACTIVATION_DELAY); assistant.setAutoActivationDelay(AUTO_ACTIVATION_DELAY);
assistant assistant
...@@ -99,7 +112,7 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration { ...@@ -99,7 +112,7 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration {
} }
public class PresentationModelObserver implements public class PresentationModelObserver implements
ICupParserASTChangeObserver, IRegisterForControllerChanges { IDisposable, ICupParserASTChangeObserver, IRegisterForControllerChanges {
private CupTokenScanner cupTokenScanner; private CupTokenScanner cupTokenScanner;
private JavaTokenScanner javaTokenScanner; private JavaTokenScanner javaTokenScanner;
private ISourceViewer sourceViewer; private ISourceViewer sourceViewer;
...@@ -111,8 +124,9 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration { ...@@ -111,8 +124,9 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration {
this.cupTokenScanner = cupTokenScanner; this.cupTokenScanner = cupTokenScanner;
this.javaTokenScanner = javaTokenScanner; this.javaTokenScanner = javaTokenScanner;
this.sourceViewer = sourceViewer; this.sourceViewer = sourceViewer;
Model model = editor.getModel(); Model model = editor.getModel();
Controller.getInstance(editor).registerObserver(this);
model.registerModelObserver(this); model.registerModelObserver(this);
// TODO: this model will likely be empty on first call?! // TODO: this model will likely be empty on first call?!
...@@ -120,6 +134,11 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration { ...@@ -120,6 +134,11 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration {
if (result != null) if (result != null)
cupTokenScanner.updateDeclarations(result.findDeclarations()); cupTokenScanner.updateDeclarations(result.findDeclarations());
} }
public void dispose() {
Controller.getInstance(editor).unregisterObserver(this);
editor.getModel().unregisterModelObserver(this);
}
@Override @Override
public EnumSet<JobsToDo> getRequiredJobs() { public EnumSet<JobsToDo> getRequiredJobs() {
...@@ -166,8 +185,8 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration { ...@@ -166,8 +185,8 @@ public class CupSourceViewerConfiguration extends SourceViewerConfiguration {
// will observe new declarations and trigger rescan of document // will observe new declarations and trigger rescan of document
// also handles changes to declared cup symbols in java blocks. // also handles changes to declared cup symbols in java blocks.
new PresentationModelObserver(cupTokenScanner, javaTokenScanner, disposables.add(new PresentationModelObserver(cupTokenScanner, javaTokenScanner,
sourceViewer); sourceViewer));
CupDamagerRepairer cupDamagerRepairer = new CupDamagerRepairer( CupDamagerRepairer cupDamagerRepairer = new CupDamagerRepairer(
cupTokenScanner); cupTokenScanner);
......
...@@ -43,7 +43,8 @@ public class CupTextEditor extends TextEditor ...@@ -43,7 +43,8 @@ public class CupTextEditor extends TextEditor
private CupContentOutlinePage outlinePage; private CupContentOutlinePage outlinePage;
private Position lastPosition; private Position lastPosition;
private boolean hasRequestedPostSaveSyntaxRefresh; private boolean hasRequestedPostSaveSyntaxRefresh;
private boolean disposed;
private static Color gray; private static Color gray;
private static Color blue; private static Color blue;
private static Color brightBlue; private static Color brightBlue;
...@@ -193,15 +194,26 @@ public class CupTextEditor extends TextEditor ...@@ -193,15 +194,26 @@ public class CupTextEditor extends TextEditor
outlinePage.jumpToPosition(position); outlinePage.jumpToPosition(position);
} }
public boolean hasBeenDisposed() {
return disposed;
}
@Override @Override
public void dispose() { public void dispose() {
System.out.println(">>>>>>>>>> DISPOSING EDITOR!"); System.out.println(">>>>>>>>>> DISPOSING EDITOR!");
Controller.getInstance(this).unregisterObserver(this);
// Note: the outline is actually disposed by eclipse.
CupSourceViewerConfiguration cvs = (CupSourceViewerConfiguration) getSourceViewerConfiguration();
cvs.dispose();
this.disposed = true;
IDocument doc = getDocument(); IDocument doc = getDocument();
hasOpened.remove(doc); hasOpened.remove(doc);
Model.deleteForDocument(doc); getModel().unregisterModelObserver(this);
Controller.getInstance(this).unregisterObserver(this);
Model.deleteForDocument(doc);
super.dispose(); super.dispose();
} }
...@@ -214,6 +226,7 @@ public class CupTextEditor extends TextEditor ...@@ -214,6 +226,7 @@ public class CupTextEditor extends TextEditor
return super.getAdapter(required); return super.getAdapter(required);
} }
public void addActions(){ public void addActions(){
if(ruler == null) if(ruler == null)
ruler = getVerticalRuler(); ruler = getVerticalRuler();
......
...@@ -17,24 +17,44 @@ import de.in.tum.www2.cup.ast.ProductionSymbolRef; ...@@ -17,24 +17,44 @@ import de.in.tum.www2.cup.ast.ProductionSymbolRef;
import de.in.tum.www2.cup.ast.Terminal; import de.in.tum.www2.cup.ast.Terminal;
import de.in.tum.www2.cup.ast.TypedNonTerminalDeclaration; import de.in.tum.www2.cup.ast.TypedNonTerminalDeclaration;
import de.in.tum.www2.cup.ast.TypedTerminalDeclaration; import de.in.tum.www2.cup.ast.TypedTerminalDeclaration;
import de.tum.in.www2.cupplugin.IDisposable;
import de.tum.in.www2.cupplugin.controller.Controller.JobsToDo; import de.tum.in.www2.cupplugin.controller.Controller.JobsToDo;
import de.tum.in.www2.cupplugin.controller.Controller;
import de.tum.in.www2.cupplugin.controller.IRegisterForControllerChanges; import de.tum.in.www2.cupplugin.controller.IRegisterForControllerChanges;
import de.tum.in.www2.cupplugin.controller.JobStatus; import de.tum.in.www2.cupplugin.controller.JobStatus;
import de.tum.in.www2.cupplugin.model.ICupParserASTChangeObserver; import de.tum.in.www2.cupplugin.model.ICupParserASTChangeObserver;
import de.tum.in.www2.cupplugin.model.Model; import de.tum.in.www2.cupplugin.model.Model;
public class CupTextHover implements ITextHover, public class CupTextHover implements ITextHover, IDisposable,
ICupParserASTChangeObserver, ICupParserASTChangeObserver, IRegisterForControllerChanges {
IRegisterForControllerChanges {
private CupTextEditor editor;
private AbstractNode prevRequestedNode; private AbstractNode prevRequestedNode;
private ParserResult ast; private ParserResult ast;
private boolean disposed;
public CupTextHover (CupTextEditor editor) { public CupTextHover (CupTextEditor editor) {
Model model = Model.getInstanceForDocument(editor.getDocument()); this.editor = editor;
model.registerModelObserver(this); Controller.getInstance(editor).registerObserver(this);
editor.getModel().registerModelObserver(this);
} }
@Override
protected void finalize() throws Throwable {
// This object is released by eclipse early and we need to ensure
// everything gets released correctly.
dispose();
super.finalize();
}
public void dispose() {
if (editor == null || disposed)
return;
disposed = true;
Controller.getInstance(editor).unregisterObserver(this);
editor.getModel().unregisterModelObserver(this);
}
@Override @Override
public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
if (hoverRegion == null) if (hoverRegion == null)
......
...@@ -189,17 +189,35 @@ public class MultiPageEditor extends MultiPageEditorPart implements ...@@ -189,17 +189,35 @@ public class MultiPageEditor extends MultiPageEditorPart implements
createGraphPage(jumper); createGraphPage(jumper);
createActionTablePage(jumper); createActionTablePage(jumper);
createReduceTablePage(jumper); createReduceTablePage(jumper);
setActivePage(previousPageIndex); setActivePage(previousPageIndex);
} }
@Override @Override
public void dispose() { public void dispose() {
editor.getModel().unregisterModelObserver(this);
Controller.getInstance(editor).unregisterObserver(this);
overviewView.dispose(); overviewView.dispose();
conflictsView.dispose(); conflictsView.dispose();
actionTableView.dispose(); actionTableView.dispose();
reduceTableView.dispose(); reduceTableView.dispose();
conflictGraphView.dispose(); conflictGraphView.dispose();
graphReduceView.dispose(); graphReduceView.dispose();
Controller.deleteForEditor(editor);
editor = null;
graphReduceZoomContribution = null;
graphReduceMenu = null;
overviewView = null;
overviewView = null;
conflictsView = null;
actionTableView = null;
reduceTableView = null;
conflictGraphView = null;
graphReduceView = null;
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
super.dispose(); super.dispose();
} }
......
...@@ -26,7 +26,7 @@ public class Model { ...@@ -26,7 +26,7 @@ public class Model {
private Statistics statistics; private Statistics statistics;
private final Object statisticsLock = new Object(); private final Object statisticsLock = new Object();
private final Object parserModelLock = new Object(); private final Object parserModelLock = new Object(); // TODO: this is also used for the modelObservers?
private final Object lalrModellock = new Object(); private final Object lalrModellock = new Object();
private List<Object> modelObservers; private List<Object> modelObservers;
...@@ -38,17 +38,17 @@ public class Model { ...@@ -38,17 +38,17 @@ public class Model {
instances.remove(document); instances.remove(document);
if (m != null) if (m != null)
m.dispose(); m.dispose();
System.out.println(">>>>>>>> REMOVED MODEL INSTANCE !!!!!!!!!!!!!!!"); System.out.println(">>>>>>>> REMOVED MODEL INSTANCE - new length: " + instances.size());
} }
} }
public void dispose() { public void dispose() {
synchronized (parserModelLock) { synchronized (parserModelLock) {
if (modelObservers != null) if (modelObservers != null)
modelObservers.clear(); modelObservers.clear();
} }
} }
public static Model getInstanceForDocument(IDocument document) { public static Model getInstanceForDocument(IDocument document) {
if (document == null) if (document == null)
return null; return null;
...@@ -71,11 +71,13 @@ public class Model { ...@@ -71,11 +71,13 @@ public class Model {
if (modelObserver == null) if (modelObserver == null)
return; return;
synchronized (parserModelLock) { synchronized (parserModelLock) {
if (this.modelObservers.contains(modelObserver))
return;
this.modelObservers.add(modelObserver); this.modelObservers.add(modelObserver);
} }
} }
public boolean deRegisterModelObserver(Object modelObserver) { public boolean unregisterModelObserver(Object modelObserver) {
if (modelObserver == null) if (modelObserver == null)
return false; return false;
synchronized (parserModelLock) { synchronized (parserModelLock) {
......