Bug 578760 - NPE and error dialog when "unexpected" editor type is
opened on breakpoint

- Don't fail with NPE if editor doesn't have document provider
installed.

- Don't close previous editor if the same was opened by the page.

- Try to reuse the editor if either the id OR the input are equal. This
avoids closing & reopening same editor that was opened via "Large File
Associations" preferences with different id.

E.g. request to open a compilation unit editor for a file size > 8 MB
will re-use already opened plain text editor, which has different editor
id  but is opened on same file input (and would not crash/hang).

Change-Id: Ie8c9fd01aff356d1a2eff0b0d373026b391a29b2
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.debug/+/190832
Reviewed-by: Simeon Andreev <simeon.danailov.andreev@gmail.com>
Reviewed-by: Andrey Loskutov <loskutov@gmx.de>
Tested-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/InstructionPointerManager.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/InstructionPointerManager.java
index f5d1db0..42b1aab 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/InstructionPointerManager.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/InstructionPointerManager.java
@@ -92,8 +92,10 @@
 	 * specified stack frame.
 	 */
 	public void addAnnotation(ITextEditor textEditor, IStackFrame frame, Annotation annotation) {
-
 		IDocumentProvider docProvider = textEditor.getDocumentProvider();
+		if (docProvider == null) {
+			return;
+		}
 		IEditorInput editorInput = textEditor.getEditorInput();
 		// If there is no annotation model, there's nothing more to do
 		IAnnotationModel annModel = docProvider.getAnnotationModel(editorInput);
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/sourcelookup/SourceLookupFacility.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/sourcelookup/SourceLookupFacility.java
index a3ee70b..c356da3 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/sourcelookup/SourceLookupFacility.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/sourcelookup/SourceLookupFacility.java
@@ -69,6 +69,7 @@
 import org.eclipse.ui.IWorkbenchPage;
 import org.eclipse.ui.IWorkbenchPart;
 import org.eclipse.ui.IWorkbenchPartReference;
+import org.eclipse.ui.IWorkbenchPartSite;
 import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.progress.UIJob;
@@ -467,7 +468,7 @@
 					// open a new editor
 					editor = openEditor(page, input, id);
 					editorForPage = editor;
-				} else if (editorForPage instanceof IReusableEditor && editorForPage.getSite().getId().equals(id)) {
+				} else if (canReuseEditor(input, id, editorForPage)) {
 					// re-use editor
 					page.reuseEditor((IReusableEditor)editorForPage, input);
 					editor = editorForPage;
@@ -477,8 +478,10 @@
 				} else {
 					// close editor, open a new one
 					editor = openEditor(page, input, id);
-					page.closeEditor(editorForPage, false);
-					editorForPage = editor;
+					if (editor != editorForPage) {
+						page.closeEditor(editorForPage, false);
+						editorForPage = editor;
+					}
 				}
 				setEditor(page, editorForPage);
 			}
@@ -489,6 +492,22 @@
 		return editor;
 	}
 
+	private static boolean canReuseEditor(IEditorInput input, String id, IEditorPart editorForPage) {
+		if (!(editorForPage instanceof IReusableEditor)) {
+			return false;
+		}
+		IWorkbenchPartSite site = editorForPage.getSite();
+		if (site == null) {
+			// editor is disposed
+			return false;
+		}
+		if (site.getId().equals(id)) {
+			return true;
+		}
+		IEditorInput editorInput = editorForPage.getEditorInput();
+		return editorInput != null && input.equals(editorInput);
+	}
+
 	/**
 	 * Positions the text editor for the given stack frame
 	 */
@@ -510,10 +529,14 @@
 	}
 
 	/**
-	 * Returns the line information for the given line in the given editor
+	 * Returns the line information for the given line in the given editor, or
+	 * {@code null} if no information could be retrieved or error happens
 	 */
 	private IRegion getLineInformation(ITextEditor editor, int lineNumber) {
 		IDocumentProvider provider= editor.getDocumentProvider();
+		if (provider == null) {
+			return null;
+		}
 		IEditorInput input= editor.getEditorInput();
 		try {
 			provider.connect(input);