package bluej.editor.stride;

import bluej.Config;
import bluej.collect.DiagnosticWithShown;
import bluej.collect.StrideEditReason;
import bluej.compiler.CompileReason;
import bluej.compiler.CompileType;
import bluej.compiler.Diagnostic;
import bluej.debugger.DebuggerField;
import bluej.debugger.DebuggerObject;
import bluej.debugger.DebuggerThread;
import bluej.debugger.gentype.GenTypeClass;
import bluej.editor.Editor;
import bluej.editor.EditorWatcher;
import bluej.editor.TextEditor;
import bluej.editor.moe.MoeSyntaxDocument;
import bluej.prefmgr.PrefMgr.PrintSize;
import bluej.parser.AssistContent;
import bluej.parser.AssistContent.CompletionKind;
import bluej.parser.ExpressionTypeInfo;
import bluej.parser.ParseUtils;
import bluej.parser.PrefixCompletionWrapper;
import bluej.parser.SourceLocation;
import bluej.parser.entity.EntityResolver;
import bluej.parser.nodes.ParsedCUNode;
import bluej.parser.symtab.ClassInfo;
import bluej.pkgmgr.JavadocResolver;
import bluej.stride.framedjava.ast.ASTUtility;
import bluej.stride.framedjava.ast.HighlightedBreakpoint;
import bluej.stride.framedjava.ast.JavaFragment;
import bluej.stride.framedjava.ast.JavaFragment.PosInSourceDoc;
import bluej.stride.framedjava.ast.JavaSource;
import bluej.stride.framedjava.ast.Loader;
import bluej.stride.framedjava.elements.CallElement;
import bluej.stride.framedjava.elements.CodeElement;
import bluej.stride.framedjava.elements.CodeElement.LocalParamInfo;
import bluej.stride.framedjava.elements.LocatableElement.LocationMap;
import bluej.stride.framedjava.elements.NormalMethodElement;
import bluej.stride.framedjava.elements.TopLevelCodeElement;
import bluej.stride.framedjava.errors.DirectSlotError;
import bluej.stride.framedjava.errors.SyntaxCodeError;
import bluej.stride.framedjava.frames.DebugInfo;
import bluej.stride.framedjava.frames.DebugVarInfo;
import bluej.stride.framedjava.frames.LocalCompletion;
import bluej.stride.framedjava.frames.LocalTypeCompletion;
import bluej.stride.framedjava.frames.PrimitiveDebugVarInfo;
import bluej.stride.framedjava.frames.ReferenceDebugVarInfo;
import bluej.stride.framedjava.slots.ExpressionSlot;
import bluej.stride.generic.AssistContentThreadSafe;
import bluej.stride.generic.InteractionManager.Kind;
import bluej.utility.Debug;
import bluej.utility.JavaReflective;
import bluej.utility.Utility;
import bluej.utility.javafx.FXPlatformConsumer;
import bluej.utility.javafx.FXPlatformRunnable;
import bluej.utility.javafx.FXRunnable;
import bluej.utility.javafx.JavaFXUtil;
import javafx.application.Platform;
import javafx.beans.property.SimpleObjectProperty;
import javafx.print.PrinterJob;
import javafx.scene.image.Image;
import threadchecker.OnThread;
import threadchecker.Tag;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.Modifier;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.stream.Stream;


| FrameEditor implements Editor, the interface to the rest of BlueJ that existed | before our frame editor was created. Because of this, not all of the methods make | sense -- see comments throughout the class. | | Most of the major functionality is actually in FrameEditorTab; this FrameEditor class | really just exists to integrate the editor into BlueJ. Also, FrameEditor can exist without | the graphical editor being opened, whereas FrameEditorTab is tied to the graphical aspect. | @OnThread(Tag.FXPlatform) public class FrameEditor implements Editor{
| Whether the code has been successfully compiled since last edit | @OnThread(Tag.FXPlatform) private boolean isCompiled; @OnThread(Tag.FXPlatform) private boolean changedSinceLastSave = false; @OnThread(Tag.FX) private String lastSavedSource = null; @OnThread(Tag.FX) private SaveJavaResult lastSavedJava = null;
| Location of the .stride file | private File frameFilename; private File javaFilename; @OnThread(Tag.FX) private final EntityResolver resolver; private final EditorWatcher watcher; private final JavadocResolver javadocResolver;
| Set to the latest version of the JavaSource. null if the editor has not yet been opened; | you can observe it to see when it becomes non-null if you want to do something when | the editor opens. | @OnThread(Tag.FX) private final SimpleObjectProperty<JavaSource> javaSource; private final bluej.pkgmgr.Package pkg; @OnThread(Tag.FX) private FrameEditorTab panel; private final DebugInfo debugInfo = new DebugInfo(); @OnThread(Tag.FXPlatform) private HighlightedBreakpoint curBreakpoint; @OnThread(Tag.FXPlatform) private final List<HighlightedBreakpoint> execHistory = new ArrayList<>();
| Stride source at last save. Assigned on FX thread only, readable on any thread. | private volatile TopLevelCodeElement lastSource;
| Errors from compilation to be shown once the editor is opened | (and thus we don't have to recompile just because the editor opens) | @OnThread(Tag.FX) private final List<QueuedError> queuedErrors = new ArrayList<>();
| A callback to call (on the Swing thread) when this editor is opened. | Callback can be accessed from any thread to be queued up, but should always | be passed to SwingUtilities.invokeLater | @OnThread(Tag.Any) private final FXPlatformRunnable callbackOnOpen; @OnThread(value = Tag.Any, requireSynchronized = true) private List<Integer> latestBreakpoints = Collections.emptyList();
| When a compile starts, we set this to false. When a compile finishes, | if it's false, we look for late errors and flip it to true. | compileFinished can get called multiple times for one compile, | so this prevents us looking for late errors twice. | @OnThread(Tag.FXPlatform) private boolean foundLateErrorsForMostRecentCompile;
| Paired with foundLateErrorsForMostRecentCompile, this is the identifier | for the most recent compile for data recording purposes, to allow the late | errors to be associated with the most recent compile which triggered them. | private int mostRecentCompileIdentifier = -1; @OnThread(Tag.Any) public synchronized List getBreakpoints() { return new ArrayList<>(latestBreakpoints); }
| A javac compile error. | @OnThread(Tag.Any) private static class QueuedError { private final long startLine, startColumn, endLine, endColumn; private final String message; private final int identifier; private QueuedError(long startLine, long startColumn, long endLine, long endColumn, String message, int identifier) { this.startLine = startLine; this.startColumn = startColumn; this.endLine = endLine; this.endColumn = endColumn; this.message = message; this.identifier = identifier; } } @OnThread(Tag.FX) public FrameEditor(File frameFilename, File javaFilename, EditorWatcher watcher, EntityResolver resolver, JavadocResolver javadocResolver, bluej.pkgmgr.Package pkg, FXPlatformRunnable callbackOnOpen) { this.frameFilename = frameFilename; this.javaFilename = javaFilename; this.watcher = watcher; this.resolver = resolver; this.javadocResolver = javadocResolver; this.pkg = pkg; this.javaSource = new SimpleObjectProperty<>(); this.callbackOnOpen = callbackOnOpen; lastSource = Loader.loadTopLevelElement(frameFilename, resolver, pkg.getQualifiedName()); }
| Create a frame editor tab. | | @param visible Whether to make the FXTabbedEditor window visible | @param toFront Whether to bring the tab to the front (i.e. select the tab) | @param openInNewWindow if this is true, the editor opens in a new window | @OnThread(Tag.FXPlatform) private void createPanel(boolean visible, boolean toFront, boolean openInNewWindow) { this.panel = new FrameEditorTab(pkg.getProject(), resolver, this, lastSource); if (visible) { if (openInNewWindow) { pkg.getProject().createNewFXTabbedEditor().addTab(this.panel, visible, toFront); } else { pkg.getProject().getDefaultFXTabbedEditor().addTab(this.panel, visible, toFront); } } else { this.panel.initialiseFX(); } panel.initialisedProperty().addListener((a, b, newVal) -> { if (newVal) { JavaFXUtil.runPlatformLater(() -> { saveFX(); findLateErrors(-1); }); } }); debugInfo.bindVarVisible(panel.debugVarVisibleProperty()); } @Override public void close() { if (panel != null) { lastSource = panel.getSource(); panel.setWindowVisible(false, false); panel.cleanup(); panel = null; } } @Override public void save() throws IOException { if (changedSinceLastSave) { SaveResult result = saveFX(); if (result.exception != null) { throw new IOException(result.exception); } if (watcher != null) { watcher.recordStrideEdit(result.javaResult.javaSourceStringContent, result.savedSource, null); } } else if (lastSavedJava == null) { lastSavedJava = saveJava(lastSource, true); } }
| Set the saved/changed status of this buffer to SAVED. | private void setSaved() { if (watcher != null) { watcher.saveEvent(this); } } private static class SaveResult { private final IOException exception; private final String savedSource; private final SaveJavaResult javaResult; public SaveResult(IOException exception) { this.exception = exception; this.savedSource = null; this.javaResult = null; } public SaveResult(String savedSource, SaveJavaResult javaResult) { this.savedSource = savedSource; this.javaResult = javaResult; this.exception = null; } }
| Saves the code, if it has been modified since it was last saved. If any IOException occurs, | it is caught and returned; otherwise, the saved XML source is returned.<p> | | The Java source is also generated if it is stale or has not yet been generated. | @OnThread(Tag.FXPlatform) private SaveResult saveFX() { try { if (!changedSinceLastSave && lastSavedSource != null) { if (lastSavedJava == null) { lastSavedJava = saveJava(lastSource, true); } return new SaveResult(lastSavedSource, lastSavedJava); } if (panel == null || panel.getSource() == null) { SaveJavaResult javaResult = saveJava(lastSource, true); return new SaveResult(Utility.serialiseCodeToString(lastSource.toXML()), javaResult); } panel.regenerateAndReparse(); TopLevelCodeElement source = panel.getSource(); if (source == null) return new SaveResult(Utility.serialiseCodeToString(lastSource.toXML()), null); try (FileOutputStream os = new FileOutputStream(frameFilename)) { Utility.serialiseCodeTo(source.toXML(), os); } lastSavedJava = saveJava(panel.getSource(), true); changedSinceLastSave = false; lastSavedSource = Utility.serialiseCodeToString(source.toXML()); setSaved(); panel.saved(); lastSource = panel.getSource(); return new SaveResult(lastSavedSource, lastSavedJava); } catch (IOException e) { return new SaveResult(e); } }
| Saves the .java file without the "warning: auto-generated" text at the top |*/ @OnThread(Tag.FXPlatform) public void saveJavaWithoutWarning() throws IOException { saveJava(lastSource, false); } private class SaveJavaResult { | |private final JavaSource javaSource; | |private final String javaSourceStringContent; | |private final LocationMap xpathLocations; | |public SaveJavaResult(JavaSource javaSource, String javaSourceStringContent, LocationMap xpathLocations) | |{ | |this.javaSource = javaSource; | |this.javaSourceStringContent = javaSourceStringContent; | |this.xpathLocations = xpathLocations; | |} | |} | |/** | @param warning Whether to include the "auto-generated" warning at the top of the file |*/ @OnThread(Tag.FXPlatform) private SaveJavaResult saveJava(TopLevelCodeElement source, boolean warning) throws IOException { if (source == null) | |return null; // Not fully loaded yet | |FileOutputStream fos = new FileOutputStream(javaFilename); | |OutputStreamWriter w = new OutputStreamWriter(fos, Charset.forName("UTF-8")); final JavaSource js = source.toJavaSource(warning); String javaString = js.toDiskJavaCodeString(); w.write(javaString); w.close(); fos.close(); // Because there may be a listener waiting on javaSource in order to show compiler error, | |// it's important that we first generate the string above, before storing it into the property, | |// to make sure all the source positions have been recorded. | |javaSource.set(js); | |return new SaveJavaResult(js, javaString, source.toXML().buildLocationMap()); | |} | |/** | Eugh. | | So: some uses of Editor in the BlueJ code (which predate frames) assume that the program | is written in text, in order to modify some aspect. That doesn't apply well to frames, so | really any use of this assumeText() method on a frame editor is wrong. Ideally, this method | should return null or throw an exception (and callers of assumeText adjusted accordingly), | but for now it returns a delegate/proxy object which throws exceptions on invalid operations. | @Override public TextEditor assumeText() { return new TextEditor() { @Override @OnThread(Tag.FXPlatform) public void setLastModified(long millisSinceEpoch) { FrameEditor.this.setLastModified(millisSinceEpoch); } @Override @OnThread(Tag.FXPlatform) public void writeMessage(String msg) { FrameEditor.this.writeMessage(msg); } @Override @OnThread(Tag.FXPlatform) public void showInterface(boolean interfaceStatus) { FrameEditor.this.showInterface(interfaceStatus); } @Override @OnThread(Tag.FXPlatform) public void setEditorVisible(boolean vis, boolean openInNewWindow) { FrameEditor.this.setEditorVisible(vis, openInNewWindow); } @Override @OnThread(Tag.FXPlatform) public void setReadOnly(boolean readOnly) { FrameEditor.this.setReadOnly(readOnly); } @Override @OnThread(Tag.FXPlatform) public void setProperty(String propertyKey, Object value) { FrameEditor.this.setProperty(propertyKey, value); } @Override @OnThread(Tag.FXPlatform) public void setCompiled(boolean compiled) { FrameEditor.this.setCompiled(compiled); } @Override @OnThread(Tag.FXPlatform) public void save() throws IOException { FrameEditor.this.save(); } @Override @OnThread(Tag.FXPlatform) public void removeStepMark() { FrameEditor.this.removeStepMark(); } @Override @OnThread(Tag.FXPlatform) public void removeBreakpoints() { FrameEditor.this.removeBreakpoints(); } @Override @OnThread(Tag.FXPlatform) public void reloadFile() { FrameEditor.this.reloadFile(); } @Override @OnThread(Tag.FXPlatform) public void refresh() { FrameEditor.this.refresh(); } @Override @OnThread(Tag.FXPlatform) public void reInitBreakpoints() { FrameEditor.this.reInitBreakpoints(); } @Override @OnThread(Tag.FXPlatform) public FXRunnable printTo(PrinterJob printerJob, PrintSize printSize, boolean printLineNumbers, boolean printBackground) { return FrameEditor.this.printTo(printerJob, printSize, printLineNumbers, printBackground); } @Override @OnThread(Tag.FXPlatform) public boolean isOpen() { return FrameEditor.this.isOpen(); } @Override @OnThread(Tag.FXPlatform) public boolean isReadOnly() { return FrameEditor.this.isReadOnly(); } @Override @OnThread(Tag.FXPlatform) public boolean isModified() { return FrameEditor.this.isModified(); } @Override @OnThread(Tag.FXPlatform) public Object getProperty(String propertyKey) { return FrameEditor.this.getProperty(propertyKey); } @Override @OnThread(Tag.FXPlatform) public void displayMessage(String message, int lineNumber, int column) { FrameEditor.this.displayMessage(message, lineNumber, column); } @Override @OnThread(Tag.FXPlatform) public boolean displayDiagnostic(Diagnostic diagnostic, int errorIndex, CompileType compileType) { return FrameEditor.this.displayDiagnostic(diagnostic, errorIndex, compileType); } @Override @OnThread(Tag.FXPlatform) public boolean setStepMark(int lineNumber, String message, boolean isBreak, DebuggerThread thread) { return FrameEditor.this.setStepMark(lineNumber, message, isBreak, thread); } @Override @OnThread(Tag.FXPlatform) public void close() { FrameEditor.this.close(); } @Override @OnThread(Tag.FXPlatform) public void changeName(String title, String filename, String javaFilename, String docFileName) { FrameEditor.this.changeName(title, filename, javaFilename, docFileName); } @Override @OnThread(Tag.FXPlatform) public TextEditor assumeText() { return this; } @Override @OnThread(Tag.FXPlatform) public boolean showFile(String filename, Charset charset, boolean compiled, String docFilename) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public void setText(SourceLocation begin, SourceLocation end, String newText) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public void setSelection(int firstlineNumber, int firstColumn, int secondLineNumber, int SecondColumn) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public void setSelection(SourceLocation begin, SourceLocation end) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public void setSelection(int lineNumber, int column, int len) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public void setCaretLocation(SourceLocation location) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public int numberOfLines() { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public void insertText(String text, boolean caretBack) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public int getTextLength() { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public String getText(SourceLocation begin, SourceLocation end) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public MoeSyntaxDocument getSourceDocument() { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public SourceLocation getSelectionEnd() { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public SourceLocation getSelectionBegin() { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public ParsedCUNode getParsedNode() { return null; } @Override @OnThread(Tag.FXPlatform) public int getOffsetFromLineColumn(SourceLocation location) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public int getLineLength(int line) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public SourceLocation getLineColumnFromOffset(int offset) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public SourceLocation getCaretLocation() { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public void clear() { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public void compileFinished(boolean successful, boolean classesKept) { throw new UnsupportedOperationException(); } @Override @OnThread(Tag.FXPlatform) public void insertAppendMethod(NormalMethodElement method, FXPlatformConsumer<Boolean> after) { FrameEditor.this.insertAppendMethod(method, after); } @Override @OnThread(Tag.FXPlatform) public void insertMethodCallInConstructor(String className, CallElement methodName, FXPlatformConsumer<Boolean> after) { FrameEditor.this.insertMethodCallInConstructor(className, methodName, after); } @Override @OnThread(Tag.FXPlatform) public FrameEditor assumeFrame() { return FrameEditor.this; } @Override @OnThread(Tag.FXPlatform) public boolean compileStarted(int compilationSequence) { return FrameEditor.this.compileStarted(compilationSequence); } @Override @OnThread(Tag.FXPlatform) public void focusMethod(String methodName, List<String> paramTypes) { FrameEditor.this.focusMethod(methodName, paramTypes); } @Override @OnThread(Tag.FXPlatform) public void setExtendsClass(String className, ClassInfo classInfo) { FrameEditor.this.setExtendsClass(className, classInfo); } @Override @OnThread(Tag.FXPlatform) public void addImplements(String className, ClassInfo classInfo) { FrameEditor.this.addImplements(className, classInfo); } @Override @OnThread(Tag.FXPlatform) public void removeExtendsClass(ClassInfo classInfo) { FrameEditor.this.removeExtendsClass(classInfo); } @Override @OnThread(Tag.FXPlatform) public void addExtendsInterface(String interfaceName, ClassInfo classInfo) { FrameEditor.this.addExtendsInterface(interfaceName, classInfo); } @Override @OnThread(Tag.FXPlatform) public void removeExtendsOrImplementsInterface(String interfaceName, ClassInfo classInfo) { FrameEditor.this.removeExtendsOrImplementsInterface(interfaceName, classInfo); } @Override @OnThread(Tag.FXPlatform) public void removeImports(List<String> importTargets) { FrameEditor.this.removeImports(importTargets); } @Override @OnThread(Tag.FXPlatform) public void setHeaderImage(Image image) { FrameEditor.this.setHeaderImage(image); } }; } @Override public void reloadFile() { } @Override public void refresh() { } @Override public void displayMessage(String message, final int lineNumber, int column) { JavaFXUtil.onceNotNull(javaSource, js -> JavaFXUtil.runNowOrLater(() -> { setVisibleFX(true, true, false); js.handleException(lineNumber); })); } @Override public boolean displayDiagnostic(final Diagnostic diagnostic, int errorIndex, CompileType compileType) { if (lastSavedJava != null && lastSavedJava.javaSource != null && lastSavedJava.xpathLocations != null) { JavaFragment fragment = lastSavedJava.javaSource.findError((int)diagnostic.getStartLine(), (int)diagnostic.getStartColumn(), (int)diagnostic.getEndLine(), (int)diagnostic.getEndColumn(), diagnostic.getMessage()); if (fragment != null) { String xpath = lastSavedJava.xpathLocations.locationFor(fragment); int start = fragment.getErrorStartPos((int)diagnostic.getStartLine(), (int)diagnostic.getStartColumn()); int end = fragment.getErrorEndPos((int)diagnostic.getEndLine(), (int)diagnostic.getEndColumn()); if (xpath != null) diagnostic.setXPath(xpath, start, end); } } if (panel != null && panel.getSource() != null) { JavaFXUtil.onceNotNull(javaSource, js -> js.handleError((int) diagnostic.getStartLine(), (int) diagnostic.getStartColumn(), (int) diagnostic.getEndLine(), (int) diagnostic.getEndColumn(), diagnostic.getMessage(), diagnostic.getIdentifier()) ); } else { queuedErrors.add(new QueuedError(diagnostic.getStartLine(), diagnostic.getStartColumn(), diagnostic.getEndLine(), diagnostic.getEndColumn(), diagnostic.getMessage(), diagnostic.getIdentifier())); } if (compileType.showEditorOnError()) { setVisibleFX(true, true, false); } return false; } @Override public boolean setStepMark(int lineNumber, String message, boolean isBreak, DebuggerThread thread) { if (true) return true; removeStepMark(); setVisibleFX(true, true, false); HashMap<String, DebugVarInfo> vars = new HashMap<String, DebugVarInfo>(); if (thread != null) { DebuggerObject currentObject = thread.getCurrentObject(0); if (currentObject != null && !currentObject.isNullObject()) { Map<String, Set<String>> restrictedClasses = pkg.getProject().getExecControls().getRestrictedClasses(); List<DebuggerField> fields = currentObject.getFields(); for (DebuggerField field : fields) { if (! Modifier.isStatic(field.getModifiers())) { String declaringClass = field.getDeclaringClassName(); Set<String> whiteList = restrictedClasses.get(declaringClass); if (whiteList == null || whiteList.contains(field.getName())) { if (field.isReferenceType()) { vars.put(field.getName(), new ReferenceDebugVarInfo(pkg, null, field)); } else { vars.put(field.getName(), new PrimitiveDebugVarInfo(field.getValueString())); } } } } } } debugInfo.addVarState(vars, execHistory.size()); panel.showDebuggerControls(thread); if (curBreakpoint != null) { curBreakpoint.removeHighlight(); curBreakpoint = null; } JavaFXUtil.onceTrue(panel.initialisedProperty(), b -> { try { JavaSource js = javaSource.get(); if (js == null) { js = saveJava(lastSource, true).javaSource; } curBreakpoint = js.handleStop(lineNumber, debugInfo); if (curBreakpoint.isBreakpointFrame()) { thread.step(); } else { if (execHistory.isEmpty() || execHistory.get(execHistory.size() - 1) != curBreakpoint) { execHistory.add(curBreakpoint); } panel.redrawExecHistory(execHistory); } } catch (IOException ioe) { Debug.reportError("Exception attempting to save Java source for Stride class", ioe); } }); return true; } @Override public void writeMessage(String msg) { } @Override public void removeStepMark() {
| | |Platform.runLater(() -> {}if (debugInfo != null) | |debugInfo.hideAllDisplays(); | |}); } @Override public void changeName(String title, String filename, String javaFilename, String docFileName) { this.frameFilename = new File(filename); this.javaFilename = new File(javaFilename); } @Override public void setCompiled(boolean compiled) { isCompiled = compiled; } @Override public void removeBreakpoints() { } @Override public void reInitBreakpoints() { watcher.clearAllBreakpoints(); if (javaSource.get() == null) { IOException e = saveFX().exception; if (e != null) Debug.reportError(e); } if (javaSource.get() != null) { JavaSource latestSource = this.javaSource.get(); watcher.clearAllBreakpoints(); List<Integer> breaks = latestSource.registerBreakpoints(this, watcher); synchronized (this) { latestBreakpoints = breaks; } } } @Override public boolean isModified() { return changedSinceLastSave; } @Override @OnThread(Tag.FXPlatform) public FXRunnable printTo(PrinterJob job, PrintSize printSize, boolean printLineNumbers, boolean printBackground) { CompletableFuture<Boolean> inited = new CompletableFuture<>(); if (panel == null) { setVisibleFX(true, false, false); } JavaFXUtil.onceTrue(panel.initialisedProperty(), init -> { inited.complete(init); }); return () -> { try { inited.get(); CompletableFuture<Boolean> done = new CompletableFuture<>(); JavaFXUtil.runPlatformLater(() -> { job.printPage(panel.getSource().getFrame().getNode()); done.complete(true); }); done.get(); } catch (InterruptedException | ExecutionException e) { Debug.reportError(e); } }; } @Override public void setReadOnly(boolean readOnly) { } @Override public boolean isReadOnly() { return false; } @Override public void showInterface(boolean interfaceStatus) { } @Override public Object getProperty(String propertyKey) { return null; } @Override public void setProperty(String propertyKey, Object value) { } @Override public void setEditorVisible(boolean vis, boolean openInNewWindow) { setVisibleFX(vis, true, openInNewWindow); } @OnThread(Tag.FXPlatform) private void setVisibleFX(boolean show, boolean bringToFront, boolean openInNewWindow) { if (panel == null && show) createPanel(show, bringToFront, openInNewWindow); } if (panel != null) { if (openInNewWindow && !panel.isWindowVisible()) { panel.setParent(pkg.getProject().createNewFXTabbedEditor(), true); } panel.setWindowVisible(show, bringToFront); if (callbackOnOpen != null && show) callbackOnOpen.run(); } if (show) { panel.withTopLevelFrame(f -> JavaFXUtil.runPlatformLater(() -> { if (!queuedErrors.isEmpty()) { Exception ex = saveFX().exception; if (ex != null) { Debug.reportError(ex); return; } final ArrayList<QueuedError> queueCopy = new ArrayList<>(queuedErrors); queuedErrors.clear(); JavaFXUtil.onceNotNull(javaSource, js -> { for (QueuedError e : queueCopy) { JavaFXUtil.runPlatformLater(() -> { js.handleError((int) e.startLine, (int) e.startColumn, (int) e.endLine, (int) e.endColumn, e.message, e.identifier); }); } JavaFXUtil.runPlatformLater(() -> panel.updateErrorOverviewBar(false)); }); } })); } } public void codeModified() { changedSinceLastSave = true; isCompiled = false; watcher.modificationEvent(this); watcher.scheduleCompilation(false, CompileReason.MODIFIED, CompileType.ERROR_CHECK_ONLY); } @Override @OnThread(Tag.FX) public FrameEditor assumeFrame() { return this; } @Override public boolean isOpen() { return false; } @Override public void compileFinished(boolean successful, boolean classesKept) { if (panel != null && panel.isWindowVisible()) { if (!foundLateErrorsForMostRecentCompile) { foundLateErrorsForMostRecentCompile = true; findLateErrors(mostRecentCompileIdentifier); mostRecentCompileIdentifier = -1; } panel.compiled(); } reInitBreakpoints(); } @OnThread(Tag.FXPlatform) private void findLateErrors(int compilationIdentifier) { panel.removeOldErrors(); TopLevelCodeElement el = panel.getSource(); if (el == null) return; Stream<CodeElement> allElements = Stream.concat(Stream.of((CodeElement)el), el.streamContained()); LocationMap rootPathMap = el.toXML().buildLocationMap(); List<Future<List<DirectSlotError>>> futures = allElements.flatMap(e -> e.findDirectLateErrors(panel, rootPathMap)).collect(Collectors.toList()); Utility.runBackground(() -> { ArrayList<DirectSlotError> allLates = new ArrayList<>(); try { for (Future<List<DirectSlotError>> f : futures) allLates.addAll(f.get()); } catch (ExecutionException | InterruptedException e) { Debug.reportError(e); } Platform.runLater(() -> { panel.updateErrorOverviewBar(false); List<DiagnosticWithShown> diagnostics = Utility.mapList(allLates, e -> e.toDiagnostic(javaFilename.getName(), frameFilename)); watcher.recordLateErrors(diagnostics, compilationIdentifier); }); }); } @Override public boolean compileStarted(int compilationSequence) { foundLateErrorsForMostRecentCompile = false; mostRecentCompileIdentifier = compilationSequence; if (panel != null) panel.flagErrorsAsOld(); else{ queuedErrors.clear(); } return earlyErrorCheck(lastSource.findEarlyErrors(), compilationSequence); }
| Given a stream of early errors, records them and returns true if there were any errors (i.e. if the stream was non-empty) | @OnThread(Tag.FXPlatform) boolean earlyErrorCheck(Stream<SyntaxCodeError> earlyErrors, int compilationIdentifier) { List<SyntaxCodeError> earlyList = earlyErrors.collect(Collectors.toList()); List<DiagnosticWithShown> diagnostics = Utility.mapList(earlyList, e -> e.toDiagnostic(javaFilename.getName(), frameFilename)); watcher.recordEarlyErrors(diagnostics, compilationIdentifier); return !earlyList.isEmpty(); } public AssistContent[] getCompletions(TopLevelCodeElement allCode, PosInSourceDoc pos, ExpressionSlot<?> completing, CodeElement codeEl) { ExpressionTypeInfo suggests = allCode.getCodeSuggestions(pos, completing); ArrayList<AssistContent> joined = new ArrayList<>(); if (suggests != null) { AssistContent[] assists = ParseUtils.getPossibleCompletions(suggests, javadocResolver, null); if (assists != null) joined.addAll(Arrays.asList(assists)); } if (suggests != null && suggests.isPlain()) { if (Config.isGreenfoot()) { JavaReflective greenfootClassRef = new JavaReflective(pkg.loadClass("greenfoot.Greenfoot")); ExpressionTypeInfo greenfootClass = new ExpressionTypeInfo(new GenTypeClass(greenfootClassRef), null, null, true, false); AssistContent[] greenfootStatic = ParseUtils.getPossibleCompletions(greenfootClass, javadocResolver, null); Arrays.stream(greenfootStatic).filter(ac -> ac.getKind() == CompletionKind.METHOD).forEach(ac -> joined.add(new PrefixCompletionWrapper(ac, "Greenfoot."))); } for (LocalParamInfo v : ASTUtility.findLocalsAndParamsInScopeAt(codeEl, false, false)) { AssistContent c = LocalCompletion.getCompletion(v.getType(), v.getName(), v.isParam()); if (c != null) joined.add(c); } } return joined.toArray(new AssistContent[0]); } public List getAvailableMembers(TopLevelCodeElement allCode, PosInSourceDoc pos, Set<CompletionKind> kinds, boolean includeOverridden) { ExpressionTypeInfo suggests = allCode.getCodeSuggestions(pos, null); if (suggests == null) return Collections.emptyList(); List<AssistContent> members; if (includeOverridden) { members = new ArrayList<>(); ParseUtils.getPossibleCompletions(suggests, javadocResolver, (ac, isOverridden) -> members.add(ac)); } else { AssistContent[] result = ParseUtils.getPossibleCompletions(suggests, javadocResolver, null); if (result == null) members = Collections.emptyList(); else{ members = Arrays.asList(result); } } return members.stream().filter(ac -> kinds == null || kinds.contains(ac.getKind())).collect(Collectors.toList()); } @Override public void insertAppendMethod(NormalMethodElement method, FXPlatformConsumer<Boolean> after) { if (panel == null) { createPanel(false, false, false); } panel.insertAppendMethod(method, after); codeModified(); } @Override public void insertMethodCallInConstructor(String className, CallElement methodName, FXPlatformConsumer<Boolean> after) { if (panel == null) { createPanel(false, false, false); } panel.insertMethodCallInConstructor(methodName, after); codeModified(); } @Override public void removeImports(List<String> importTargets) { if (panel == null) { createPanel(false, false, false); } panel.removeImports(importTargets); codeModified(); }
| Set the header image (in the tab header) for this editor | @param image The image to use (any size). | @Override public void setHeaderImage(Image image) { if (panel != null) { panel.setHeaderImage(image); } } @Override @OnThread(Tag.FXPlatform) public void setLastModified(long millisSinceEpoch) { } @OnThread(Tag.FX) public TopLevelCodeElement getSource() { return panel.getSource(); } @OnThread(Tag.FXPlatform) public List getLocalTypes(Class<?> superType, boolean includeSelf, Set<Kind> kinds) { return pkg.getClassTargets() .stream() .filter(ct -> { if (superType != null) { ClassInfo info = ct.getSourceInfo().getInfoIfAvailable(); if (info == null) return false; boolean hasSuperType = false; hasSuperType |= superType.getName().equals(info.getSuperclass()); hasSuperType |= info.getImplements().stream().anyMatch(s -> superType.getName().equals(s)); if (!hasSuperType) return false; } if (ct.isInterface()) return kinds.contains(Kind.INTERFACE); else if (ct.isEnum()) return kinds.contains(Kind.ENUM); else{ return kinds.contains(Kind.CLASS_FINAL) || kinds.contains(Kind.CLASS_NON_FINAL); } }) .map(ct -> new AssistContentThreadSafe(LocalTypeCompletion.getCompletion(ct))) .collect(Collectors.toList()); } public void showNextError() { panel.nextError(); } @Override public void focusMethod(String methodName, List<String> paramTypes) { if (panel == null) { createPanel(true, true, false); } panel.focusMethod(methodName); } public JavadocResolver getJavadocResolver() { return javadocResolver; } @OnThread(Tag.Any) public EditorWatcher getWatcher() { return watcher; } @OnThread(Tag.FXPlatform) public void recordEdits(StrideEditReason reason) { SaveResult result = saveFX(); if (result.exception == null) { watcher.recordStrideEdit(result.javaResult.javaSourceStringContent, result.savedSource, reason); } else{ Debug.reportError(result.exception); } } @Override public void addImplements(String className, ClassInfo classInfo) { if (panel == null) { createPanel(false, false, false); } JavaFXUtil.onceTrue(panel.initialisedProperty(), p -> panel.addImplements(className)); } @Override public void setExtendsClass(String className, ClassInfo classInfo) { if (panel == null) { createPanel(false, false, false); } JavaFXUtil.onceTrue(panel.initialisedProperty(), p -> panel.addExtends(className)); } @Override public void removeExtendsClass(ClassInfo classInfo) { if (panel == null) { createPanel(false, false, false); } JavaFXUtil.onceTrue(panel.initialisedProperty(), p -> panel.removeExtendsClass()); } @Override public void addExtendsInterface(String interfaceName, ClassInfo classInfo) { if (panel == null) { createPanel(false, false, false); } JavaFXUtil.onceTrue(panel.initialisedProperty(), p -> panel.addExtends(interfaceName)); } @Override public void removeExtendsOrImplementsInterface(String interfaceName, ClassInfo classInfo) { if (panel == null) { createPanel(false, false, false); } JavaFXUtil.onceTrue(panel.initialisedProperty(), p -> panel.removeExtendsOrImplementsInterface(interfaceName)); }
| Get the package of the class being edited by this editor. | public bluej.pkgmgr.Package getPackage() { return pkg; } }
top, use, map, class FrameEditor

.   getBreakpoints

top, use, map, class FrameEditor . QueuedError

.   QueuedError
.   FrameEditor
.   createPanel
.   close
.   save
.   setSaved

top, use, map, class SaveResult

.   SaveResult
.   SaveResult
.   saveFX
.   assumeText
.   setLastModified
.   writeMessage
.   showInterface
.   setEditorVisible
.   setReadOnly
.   setProperty
.   setCompiled
.   save
.   removeStepMark
.   removeBreakpoints
.   reloadFile
.   refresh
.   reInitBreakpoints
.   printTo
.   isOpen
.   isReadOnly
.   isModified
.   getProperty
.   displayMessage
.   displayDiagnostic
.   setStepMark
.   close
.   changeName
.   assumeText
.   showFile
.   setText
.   setSelection
.   setSelection
.   setSelection
.   setCaretLocation
.   numberOfLines
.   insertText
.   getTextLength
.   getText
.   getSourceDocument
.   getSelectionEnd
.   getSelectionBegin
.   getParsedNode
.   getOffsetFromLineColumn
.   getLineLength
.   getLineColumnFromOffset
.   getCaretLocation
.   clear
.   compileFinished
.   insertAppendMethod
.   insertMethodCallInConstructor
.   assumeFrame
.   compileStarted
.   focusMethod
.   setExtendsClass
.   addImplements
.   removeExtendsClass
.   addExtendsInterface
.   removeExtendsOrImplementsInterface
.   removeImports
.   setHeaderImage
.   reloadFile
.   refresh
.   displayMessage
.   displayDiagnostic
.   setStepMark
.   writeMessage
.   removeStepMark
.   changeName
.   setCompiled
.   removeBreakpoints
.   reInitBreakpoints
.   isModified
.   printTo
.   setReadOnly
.   isReadOnly
.   showInterface
.   getProperty
.   setProperty
.   setEditorVisible
.   setVisibleFX
.   codeModified
.   assumeFrame
.   isOpen
.   compileFinished
.   findLateErrors
.   compileStarted
.   getCompletions
.   getAvailableMembers
.   insertAppendMethod
.   insertMethodCallInConstructor
.   removeImports
.   setHeaderImage
.   setLastModified
.   getSource
.   getLocalTypes
.   showNextError
.   focusMethod
.   getJavadocResolver
.   getWatcher
.   recordEdits
.   addImplements
.   setExtendsClass
.   removeExtendsClass
.   addExtendsInterface
.   removeExtendsOrImplementsInterface
.   getPackage




1742 neLoCode + 69 LoComm