/******************************************************************************* * Copyright (c) 2000, 2017 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.debug.ui.actions; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IBreakpointManager; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension2; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IPackageDeclaration; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeParameter; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.core.SourceRange; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ClassInstanceCreation; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.NodeFinder; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SimpleType; import org.eclipse.jdt.debug.core.IJavaBreakpoint; import org.eclipse.jdt.debug.core.IJavaClassPrepareBreakpoint; import org.eclipse.jdt.debug.core.IJavaFieldVariable; import org.eclipse.jdt.debug.core.IJavaLineBreakpoint; import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint; import org.eclipse.jdt.debug.core.IJavaType; import org.eclipse.jdt.debug.core.IJavaWatchpoint; import org.eclipse.jdt.debug.core.JDIDebugModel; import org.eclipse.jdt.internal.corext.template.java.CompilationUnitContext; import org.eclipse.jdt.internal.corext.template.java.CompilationUnitContextType; import org.eclipse.jdt.internal.corext.template.java.JavaContextType; import org.eclipse.jdt.internal.debug.core.JavaDebugUtils; import org.eclipse.jdt.internal.debug.core.breakpoints.ValidBreakpointLocationLocator; import org.eclipse.jdt.internal.debug.ui.BreakpointUtils; import org.eclipse.jdt.internal.debug.ui.DebugWorkingCopyManager; import org.eclipse.jdt.internal.debug.ui.IJDIPreferencesConstants; import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; import org.eclipse.jdt.internal.ui.text.template.contentassist.TemplateEngine; import org.eclipse.jdt.internal.ui.text.template.contentassist.TemplateProposal; import org.eclipse.jdt.ui.IWorkingCopyManager; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jdt.ui.SharedASTProvider; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.IVerticalRulerInfo; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.jface.text.templates.TemplateException; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.SimpleMarkerAnnotation; /** * Toggles a line breakpoint in a Java editor. * * @since 3.0 */ public class ToggleBreakpointAdapter implements IToggleBreakpointsTargetExtension2 { private static final String EMPTY_STRING = ""; //$NON-NLS-1$ /** * Constructor */ public ToggleBreakpointAdapter() { // initialize helper in UI thread ActionDelegateHelper.getDefault(); } /** * Returns the <code>IType</code> for the given selection * @param selection the current text selection * @return the <code>IType</code> for the text selection or <code>null</code> */ protected IType getType(ITextSelection selection) { IMember member = ActionDelegateHelper.getDefault().getCurrentMember(selection); IType type = null; if (member instanceof IType) { type = (IType) member; } else if (member != null) { type = member.getDeclaringType(); } // bug 52385: we don't want local and anonymous types from compilation // unit, // we are getting 'not-always-correct' names for them. try { while (type != null && !type.isBinary() && type.isLocal()) { type = type.getDeclaringType(); } } catch (JavaModelException e) { JDIDebugUIPlugin.log(e); } return type; } /** * Returns the IType associated with the <code>IJavaElement</code> passed in * @param element the <code>IJavaElement</code> to get the type from * @return the corresponding <code>IType</code> for the <code>IJavaElement</code>, or <code>null</code> if there is not one. * @since 3.3 */ protected IType getType(IJavaElement element) { switch(element.getElementType()) { case IJavaElement.FIELD: { return ((IField)element).getDeclaringType(); } case IJavaElement.METHOD: { return ((IMethod)element).getDeclaringType(); } case IJavaElement.TYPE: { return (IType)element; } default: { return null; } } } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleLineBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { toggleLineBreakpoints(part, selection, false, null); } /** * Toggles a line breakpoint. * @param part the currently active workbench part * @param selection the current selection * @param bestMatch if we should make a best match or not */ public void toggleLineBreakpoints(final IWorkbenchPart part, final ISelection selection, final boolean bestMatch, final ValidBreakpointLocationLocator locator) { Job job = new Job("Toggle Line Breakpoint") { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { return doLineBreakpointToggle(selection, part, locator, bestMatch, monitor); } }; job.setPriority(Job.INTERACTIVE); job.setSystem(true); job.schedule(); } /* * (non-Javadoc) * * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleLineBreakpoints(IWorkbenchPart, * ISelection) */ @Override public boolean canToggleLineBreakpoints(IWorkbenchPart part, ISelection selection) { if (isRemote(part, selection)) { return false; } return selection instanceof ITextSelection; } /* * (non-Javadoc) * * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart, * org.eclipse.jface.viewers.ISelection) */ @Override public void toggleMethodBreakpoints(final IWorkbenchPart part, final ISelection finalSelection) { Job job = new Job("Toggle Method Breakpoints") { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } try { BreakpointToggleUtils.report(null, part); ISelection selection = finalSelection; if(!(selection instanceof IStructuredSelection)) { selection = translateToMembers(part, selection); } boolean isInterface = isInterface(selection, part); if (selection instanceof IStructuredSelection) { IMethod[] members = getMethods((IStructuredSelection) selection, isInterface); if (members.length == 0) { if(isInterface) { BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_6, part); } else { BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_9, part); } return Status.OK_STATUS; } IJavaBreakpoint breakpoint = null; ISourceRange range = null; Map<String, Object> attributes = null; IType type = null; String signature = null; String mname = null; for (int i = 0, length = members.length; i < length; i++) { breakpoint = getMethodBreakpoint(members[i]); if (breakpoint == null) { int start = -1; int end = -1; range = members[i].getNameRange(); if (range != null) { start = range.getOffset(); end = start + range.getLength(); } attributes = new HashMap<>(10); BreakpointUtils.addJavaBreakpointAttributes(attributes, members[i]); type = members[i].getDeclaringType(); signature = members[i].getSignature(); mname = members[i].getElementName(); if (members[i].isConstructor()) { mname = "<init>"; //$NON-NLS-1$ if (type.isEnum()) { signature = "(Ljava.lang.String;I" + signature.substring(1); //$NON-NLS-1$ } } if (!type.isBinary()) { signature = resolveMethodSignature(members[i]); if (signature == null) { BreakpointToggleUtils.report(ActionMessages.ManageMethodBreakpointActionDelegate_methodNonAvailable, part); return Status.OK_STATUS; } } IJavaMethodBreakpoint methodBreakpoint = JDIDebugModel.createMethodBreakpoint(BreakpointUtils.getBreakpointResource(members[i]), getQualifiedName(type), mname, signature, true, false, false, -1, start, end, 0, true, attributes); if (BreakpointToggleUtils.isToggleTracepoints() && finalSelection instanceof ITextSelection && part instanceof CompilationUnitEditor) { String pattern = getCodeTemplate((ITextSelection) finalSelection, (CompilationUnitEditor) part); if (pattern != null) { pattern.trim(); pattern = pattern.replaceAll("\\\t", ""); //$NON-NLS-1$//$NON-NLS-2$ methodBreakpoint.setCondition(pattern); methodBreakpoint.setConditionEnabled(true); methodBreakpoint.setConditionSuspendOnTrue(true); } BreakpointToggleUtils.setUnsetTracepoints(false); } } else { if (BreakpointToggleUtils.isToggleTracepoints()) { deleteTracepoint(breakpoint, part, monitor); BreakpointToggleUtils.setUnsetTracepoints(false); } else { deleteBreakpoint(breakpoint, part, monitor); } } } } else { BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_4, part); return Status.OK_STATUS; } } catch (CoreException e) { return e.getStatus(); } finally { BreakpointToggleUtils.setUnsetTracepoints(false); } return Status.OK_STATUS; } }; job.setPriority(Job.INTERACTIVE); job.setSystem(true); job.schedule(); } /** * Performs the actual toggling of the line breakpoint * @param selection the current selection (from the editor or view) * @param part the active part * @param locator the locator, may be <code>null</code> * @param bestMatch if we should consider the best match rather than an exact match * @param monitor progress reporting * @return the status of the toggle * @since 3.8 */ IStatus doLineBreakpointToggle(ISelection selection, IWorkbenchPart part, ValidBreakpointLocationLocator locator, boolean bestMatch, IProgressMonitor monitor) { ITextEditor editor = getTextEditor(part); if (editor != null && selection instanceof ITextSelection) { if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } ITextSelection tsel = (ITextSelection) selection; if(tsel.getStartLine() < 0) { return Status.CANCEL_STATUS; } try { BreakpointToggleUtils.report(null, part); ISelection sel = selection; if(!(selection instanceof IStructuredSelection)) { sel = translateToMembers(part, selection); } if(sel instanceof IStructuredSelection) { IMember member = (IMember) ((IStructuredSelection)sel).getFirstElement(); IType type = null; if(member.getElementType() == IJavaElement.TYPE) { type = (IType) member; } else { type = member.getDeclaringType(); } if (locator == null && BreakpointToggleUtils.isToggleTracepoints()) { CompilationUnit cUnit = parseCompilationUnit(type.getTypeRoot()); locator = new ValidBreakpointLocationLocator(cUnit, tsel.getStartLine() + 1, true, bestMatch); cUnit.accept(locator); } String tname = null; IJavaProject project = type.getJavaProject(); if (locator == null || (project != null && !project.isOnClasspath(type))) { tname = createQualifiedTypeName(type); } else { tname = locator.getFullyQualifiedTypeName(); } if (tname == null) { return Status.CANCEL_STATUS; } IResource resource = BreakpointUtils.getBreakpointResource(type); int lnumber = locator == null ? tsel.getStartLine() + 1 : locator.getLineLocation(); IJavaLineBreakpoint existingBreakpoint = JDIDebugModel.lineBreakpointExists(resource, tname, lnumber); if (existingBreakpoint != null) { if (BreakpointToggleUtils.isToggleTracepoints()) { deleteTracepoint(existingBreakpoint, editor, monitor); BreakpointToggleUtils.setUnsetTracepoints(false); } else { deleteBreakpoint(existingBreakpoint, editor, monitor); } return Status.OK_STATUS; } Map<String, Object> attributes = new HashMap<>(10); IDocumentProvider documentProvider = editor.getDocumentProvider(); if (documentProvider == null) { return Status.CANCEL_STATUS; } IDocument document = documentProvider.getDocument(editor.getEditorInput()); int charstart = -1, charend = -1; try { IRegion line = document.getLineInformation(lnumber - 1); charstart = line.getOffset(); charend = charstart + line.getLength(); } catch (BadLocationException ble) {JDIDebugUIPlugin.log(ble);} BreakpointUtils.addJavaBreakpointAttributes(attributes, type); IJavaLineBreakpoint breakpoint = JDIDebugModel.createLineBreakpoint(resource, tname, lnumber, charstart, charend, 0, true, attributes); if (BreakpointToggleUtils.isToggleTracepoints() && selection instanceof ITextSelection && part instanceof CompilationUnitEditor) { String pattern = getCodeTemplate((ITextSelection) selection, (CompilationUnitEditor) part); if (pattern != null) { pattern.trim(); pattern = pattern.replaceAll("\\\t", ""); //$NON-NLS-1$//$NON-NLS-2$ breakpoint.setCondition(pattern); breakpoint.setConditionEnabled(true); breakpoint.setConditionSuspendOnTrue(true); } BreakpointToggleUtils.setUnsetTracepoints(false); } if (locator == null) { new BreakpointLocationVerifierJob(document, parseCompilationUnit(type.getTypeRoot()), breakpoint, lnumber, tname, type, editor, bestMatch).schedule(); } if (BreakpointToggleUtils.isToggleTracepoints()) { BreakpointToggleUtils.setUnsetTracepoints(false); } } else { BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_3, part); return Status.OK_STATUS; } } catch (CoreException ce) {return ce.getStatus();} finally { BreakpointToggleUtils.setUnsetTracepoints(false); } } return Status.OK_STATUS; } /** * Toggles a class load breakpoint * @param part the part * @param selection the current selection * @since 3.3 */ public void toggleClassBreakpoints(final IWorkbenchPart part, final ISelection selection) { Job job = new Job("Toggle Class Load Breakpoints") { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } try { BreakpointToggleUtils.report(null, part); ISelection sel = selection; if(!(selection instanceof IStructuredSelection)) { sel = translateToMembers(part, selection); } if(isInterface(sel, part)) { BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_1, part); return Status.OK_STATUS; } if(sel instanceof IStructuredSelection) { IMember member = (IMember)((IStructuredSelection)sel).getFirstElement(); IType type = (IType) member; IJavaBreakpoint existing= getClassLoadBreakpoint(type); if (existing != null) { deleteBreakpoint(existing, part, monitor); return Status.OK_STATUS; } HashMap<String, Object> map = new HashMap<>(10); BreakpointUtils.addJavaBreakpointAttributes(map, type); ISourceRange range= type.getNameRange(); int start = -1; int end = -1; if (range != null) { start = range.getOffset(); end = start + range.getLength(); } JDIDebugModel.createClassPrepareBreakpoint(BreakpointUtils.getBreakpointResource(member), getQualifiedName(type), IJavaClassPrepareBreakpoint.TYPE_CLASS, start, end, true, map); } else { BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_0, part); return Status.OK_STATUS; } } catch (CoreException e) { return e.getStatus(); } return Status.OK_STATUS; } }; job.setPriority(Job.INTERACTIVE); job.setSystem(true); job.schedule(); } /** * Returns the class load breakpoint for the specified type or null if none found * @param type the type to search for a class load breakpoint for * @return the existing class load breakpoint, or null if none * @throws CoreException * @since 3.3 */ protected IJavaBreakpoint getClassLoadBreakpoint(IType type) throws CoreException { IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(JDIDebugModel.getPluginIdentifier()); for (int i = 0; i < breakpoints.length; i++) { IJavaBreakpoint breakpoint= (IJavaBreakpoint)breakpoints[i]; if (breakpoint instanceof IJavaClassPrepareBreakpoint && getQualifiedName(type).equals(breakpoint.getTypeName())) { return breakpoint; } } return null; } /** * Returns the binary name for the {@link IType} derived from its {@link ITypeBinding}. * <br><br> * If the {@link ITypeBinding} cannot be derived this method falls back to calling * {@link #createQualifiedTypeName(IType)} to try and compose the type name. * @param type * @return the binary name for the given {@link IType} * @since 3.6 */ String getQualifiedName(IType type) throws JavaModelException { IJavaProject project = type.getJavaProject(); if (project != null && project.isOnClasspath(type) && needsBindings(type)) { CompilationUnit cuNode = parseCompilationUnit(type.getTypeRoot()); ISourceRange nameRange = type.getNameRange(); if (SourceRange.isAvailable(nameRange)) { ASTNode node = NodeFinder.perform(cuNode, nameRange); if (node instanceof SimpleName) { IBinding binding; if (node.getLocationInParent() == SimpleType.NAME_PROPERTY && node.getParent().getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY) { binding = ((ClassInstanceCreation) node.getParent().getParent()).resolveTypeBinding(); } else { binding = ((SimpleName) node).resolveBinding(); } if (binding instanceof ITypeBinding) { String name = ((ITypeBinding) binding).getBinaryName(); if (name != null) { return name; } } } } } return createQualifiedTypeName(type); } /** * Checks if the type or any of its enclosing types are local types. * @param type * @return <code>true</code> if the type or a parent type are a local type * @throws JavaModelException * @since 3.6 */ boolean needsBindings(IType type) throws JavaModelException { if(type.isMember()) { if(type.isLocal() && !type.isAnonymous()) { return true; } IJavaElement parent = type.getParent(); IType ptype = null; while(parent != null) { if(parent.getElementType() == IJavaElement.TYPE) { ptype = (IType) parent; if(ptype.isLocal() && !ptype.isAnonymous()) { return true; } } parent = parent.getParent(); } } return false; } /** * Returns the package qualified name, while accounting for the fact that a source file might * not have a project * @param type the type to ensure the package qualified name is created for * @return the package qualified name * @since 3.3 */ String createQualifiedTypeName(IType type) { String tname = pruneAnonymous(type); try { String packName = null; if (type.isBinary()) { packName = type.getPackageFragment().getElementName(); } else { IPackageDeclaration[] pd = type.getCompilationUnit().getPackageDeclarations(); if(pd.length > 0) { packName = pd[0].getElementName(); } } if(packName != null && !packName.equals(EMPTY_STRING)) { tname = packName+"."+tname; //$NON-NLS-1$ } } catch (JavaModelException e) {} return tname; } /** * Prunes out all naming occurrences of anonymous inner types, since these types have no names * and cannot be derived visiting an AST (no positive type name matching while visiting ASTs) * @param type * @return the compiled type name from the given {@link IType} with all occurrences of anonymous inner types removed * @since 3.4 */ private String pruneAnonymous(IType type) { StringBuffer buffer = new StringBuffer(); IJavaElement parent = type; while(parent != null) { if(parent.getElementType() == IJavaElement.TYPE){ IType atype = (IType) parent; try { if(!atype.isAnonymous()) { if(buffer.length() > 0) { buffer.insert(0, '$'); } buffer.insert(0, atype.getElementName()); } } catch(JavaModelException jme) {} } parent = parent.getParent(); } return buffer.toString(); } /** * gets the <code>IJavaElement</code> from the editor input * @param input the current editor input * @return the corresponding <code>IJavaElement</code> * @since 3.3 */ private IJavaElement getJavaElement(IEditorInput input) { IJavaElement je = JavaUI.getEditorInputJavaElement(input); if(je != null) { return je; } //try to get from the working copy manager return DebugWorkingCopyManager.getWorkingCopy(input, false); } /* * (non-Javadoc) * * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart, * org.eclipse.jface.viewers.ISelection) */ @Override public boolean canToggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) { if (isRemote(part, selection)) { return false; } if (selection instanceof IStructuredSelection) { IStructuredSelection ss = (IStructuredSelection) selection; return getMethods(ss, isInterface(selection, part)).length > 0; } return (selection instanceof ITextSelection) && isMethod((ITextSelection) selection, part); } /** * Returns whether the given part/selection is remote (viewing a repository) * * @param part * @param selection * @return */ protected boolean isRemote(IWorkbenchPart part, ISelection selection) { if (selection instanceof IStructuredSelection) { IStructuredSelection ss = (IStructuredSelection) selection; Object element = ss.getFirstElement(); if(element instanceof IMember) { IMember member = (IMember) element; return !member.getJavaProject().getProject().exists(); } } ITextEditor editor = getTextEditor(part); if (editor != null) { IEditorInput input = editor.getEditorInput(); Object adapter = Platform.getAdapterManager().getAdapter(input, "org.eclipse.team.core.history.IFileRevision"); //$NON-NLS-1$ return adapter != null; } return false; } /** * Returns the text editor associated with the given part or <code>null</code> * if none. In case of a multi-page editor, this method should be used to retrieve * the correct editor to perform the breakpoint operation on. * * @param part workbench part * @return text editor part or <code>null</code> */ protected ITextEditor getTextEditor(IWorkbenchPart part) { if (part instanceof ITextEditor) { return (ITextEditor) part; } return part.getAdapter(ITextEditor.class); } /** * Returns the methods from the selection, or an empty array * @param selection the selection to get the methods from * @return an array of the methods from the selection or an empty array */ protected IMethod[] getMethods(IStructuredSelection selection, boolean isInterace) { if (selection.isEmpty()) { return new IMethod[0]; } List<IMethod> methods = new ArrayList<>(selection.size()); Iterator<?> iterator = selection.iterator(); while (iterator.hasNext()) { Object thing = iterator.next(); try { if (thing instanceof IMethod) { IMethod method = (IMethod) thing; if(isInterace){ if (Flags.isDefaultMethod(method.getFlags()) || Flags.isStatic(method.getFlags())) { methods.add(method); } } else if (!Flags.isAbstract(method.getFlags())) { methods.add(method); } } } catch (JavaModelException e) {} } return methods.toArray(new IMethod[methods.size()]); } /** * Returns the methods from the selection, or an empty array * @param selection the selection to get the methods from * @return an array of the methods from the selection or an empty array */ protected IMethod[] getInterfaceMethods(IStructuredSelection selection) { if (selection.isEmpty()) { return new IMethod[0]; } List<IMethod> methods = new ArrayList<>(selection.size()); Iterator<?> iterator = selection.iterator(); while (iterator.hasNext()) { Object thing = iterator.next(); try { if (thing instanceof IMethod) { IMethod method = (IMethod) thing; if (Flags.isDefaultMethod(method.getFlags())) { methods.add(method); } } } catch (JavaModelException e) {} } return methods.toArray(new IMethod[methods.size()]); } /** * Returns if the text selection is a valid method or not * @param selection the text selection * @param part the associated workbench part * @return true if the selection is a valid method, false otherwise */ private boolean isMethod(ITextSelection selection, IWorkbenchPart part) { ITextEditor editor = getTextEditor(part); if (editor != null) { IJavaElement element = getJavaElement(editor.getEditorInput()); if (element != null) { try { if (element instanceof ICompilationUnit) { element = ((ICompilationUnit) element).getElementAt(selection.getOffset()); } else if (element instanceof IClassFile) { element = ((IClassFile) element).getElementAt(selection.getOffset()); } if (element != null && element.getElementType() == IJavaElement.METHOD) { IMethod method = (IMethod) element; if (method.getDeclaringType().isAnonymous()) { return false; } return true; } } catch (JavaModelException e) { return false; } } } return false; } /** * Returns a list of <code>IField</code> and <code>IJavaFieldVariable</code> in the given selection. * When an <code>IField</code> can be resolved for an <code>IJavaFieldVariable</code>, it is * returned in favour of the variable. * * @param selection * @return list of <code>IField</code> and <code>IJavaFieldVariable</code>, possibly empty * @throws CoreException */ protected List<Object> getFields(IStructuredSelection selection) throws CoreException { if (selection.isEmpty()) { return Collections.EMPTY_LIST; } List<Object> fields = new ArrayList<>(selection.size()); Iterator<?> iterator = selection.iterator(); while (iterator.hasNext()) { Object thing = iterator.next(); if (thing instanceof IField) { fields.add(thing); } else if (thing instanceof IJavaFieldVariable) { IField field = getField((IJavaFieldVariable) thing); if (field == null) { fields.add(thing); } else { fields.add(field); } } } return fields; } /** * Returns if the structured selection is itself or is part of an interface * @param selection the current selection * @return true if the selection is part of an interface, false otherwise * @since 3.2 */ private boolean isInterface(ISelection selection, IWorkbenchPart part) { try { ISelection sel = selection; if(!(sel instanceof IStructuredSelection)) { sel = translateToMembers(part, selection); } if(sel instanceof IStructuredSelection) { Object obj = ((IStructuredSelection)sel).getFirstElement(); if(obj instanceof IMember) { IMember member = (IMember) ((IStructuredSelection)sel).getFirstElement(); if(member.getElementType() == IJavaElement.TYPE) { return ((IType)member).isInterface(); } return member.getDeclaringType().isInterface(); } else if(obj instanceof IJavaFieldVariable) { IJavaFieldVariable var = (IJavaFieldVariable) obj; IType type = JavaDebugUtils.resolveType(var.getDeclaringType()); return type != null && type.isInterface(); } } } catch (CoreException e1) {} return false; } /** * Returns if the text selection is a field selection or not * @param selection the text selection * @param part the associated workbench part * @return true if the text selection is a valid field for a watchpoint, false otherwise * @since 3.3 */ private boolean isField(ITextSelection selection, IWorkbenchPart part) { ITextEditor editor = getTextEditor(part); if(editor != null) { IJavaElement element = getJavaElement(editor.getEditorInput()); if(element != null) { try { if(element instanceof ICompilationUnit) { element = ((ICompilationUnit) element).getElementAt(selection.getOffset()); } else if(element instanceof IClassFile) { element = ((IClassFile) element).getElementAt(selection.getOffset()); } return element != null && element.getElementType() == IJavaElement.FIELD; } catch (JavaModelException e) {return false;} } } return false; } /** * Determines if the selection is a field or not * @param selection the current selection * @return true if the selection is a field false otherwise */ private boolean isFields(IStructuredSelection selection) { if (!selection.isEmpty()) { try { Iterator<?> iterator = selection.iterator(); while (iterator.hasNext()) { Object thing = iterator.next(); if (thing instanceof IField) { int flags = ((IField)thing).getFlags(); return !Flags.isFinal(flags) & !(Flags.isFinal(flags) & Flags.isStatic(flags)); } else if(thing instanceof IJavaFieldVariable) { IJavaFieldVariable fv = (IJavaFieldVariable)thing; return !fv.isFinal() & !(fv.isFinal() & fv.isStatic()); } } } catch(JavaModelException e) {return false;} catch(DebugException de) {return false;} } return false; } /* * (non-Javadoc) * * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleWatchpoints(org.eclipse.ui.IWorkbenchPart, * org.eclipse.jface.viewers.ISelection) */ @Override public void toggleWatchpoints(final IWorkbenchPart part, final ISelection finalSelection) { Job job = new Job("Toggle Watchpoints") { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } try { BreakpointToggleUtils.report(null, part); ISelection selection = finalSelection; if(!(selection instanceof IStructuredSelection)) { selection = translateToMembers(part, finalSelection); } if(isInterface(selection, part)) { BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_5, part); return Status.OK_STATUS; } boolean allowed = false; if (selection instanceof IStructuredSelection) { List<Object> fields = getFields((IStructuredSelection) selection); if (fields.isEmpty()) { BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_10, part); return Status.OK_STATUS; } Iterator<Object> theFields = fields.iterator(); IField javaField = null; IResource resource = null; String typeName = null; String fieldName = null; Object element = null; Map<String, Object> attributes = null; IJavaBreakpoint breakpoint = null; while (theFields.hasNext()) { element = theFields.next(); if (element instanceof IField) { javaField = (IField) element; IType type = javaField.getDeclaringType(); typeName = getQualifiedName(type); fieldName = javaField.getElementName(); int f = javaField.getFlags(); boolean fin = Flags.isFinal(f); if (fin) { fin = javaField.getConstant() != null; // watch point is allowed if no constant value } allowed = !(fin) & !(Flags.isStatic(f) & fin); } else if (element instanceof IJavaFieldVariable) { IJavaFieldVariable var = (IJavaFieldVariable) element; typeName = var.getDeclaringType().getName(); fieldName = var.getName(); boolean fin = var.isFinal(); if (fin) { fin = javaField.getConstant() != null; // watch point is allowed if no constant value } allowed = !(fin) & !(var.isStatic() & fin); } breakpoint = getWatchpoint(typeName, fieldName); if (breakpoint == null) { if(!allowed) { return doLineBreakpointToggle(finalSelection, part, null, true, monitor); } int start = -1; int end = -1; attributes = new HashMap<>(10); if (javaField == null) { resource = ResourcesPlugin.getWorkspace().getRoot(); } else { IType type = javaField.getDeclaringType(); ISourceRange range = javaField.getNameRange(); if (range != null) { start = range.getOffset(); end = start + range.getLength(); } BreakpointUtils.addJavaBreakpointAttributes(attributes, javaField); resource = BreakpointUtils.getBreakpointResource(type); } JDIDebugModel.createWatchpoint(resource, typeName, fieldName, -1, start, end, 0, true, attributes); } else { deleteBreakpoint(breakpoint, part, monitor); } } } else { BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_2, part); return Status.OK_STATUS; } } catch (CoreException e) {return e.getStatus();} return Status.OK_STATUS; } }; job.setPriority(Job.INTERACTIVE); job.setSystem(true); job.schedule(); } /** * Returns any existing watchpoint for the given field, or <code>null</code> if none. * * @param typeName fully qualified type name on which watchpoint may exist * @param fieldName field name * @return any existing watchpoint for the given field, or <code>null</code> if none * @throws CoreException */ private IJavaWatchpoint getWatchpoint(String typeName, String fieldName) throws CoreException { IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager(); IBreakpoint[] breakpoints = breakpointManager.getBreakpoints(JDIDebugModel.getPluginIdentifier()); for (int i = 0; i < breakpoints.length; i++) { IBreakpoint breakpoint = breakpoints[i]; if (breakpoint instanceof IJavaWatchpoint) { IJavaWatchpoint watchpoint = (IJavaWatchpoint) breakpoint; if (typeName.equals(watchpoint.getTypeName()) && fieldName.equals(watchpoint.getFieldName())) { return watchpoint; } } } return null; } /** * Returns the resolved signature of the given method * @param method method to resolve * @return the resolved method signature or <code>null</code> if none * @throws JavaModelException * @since 3.4 */ public static String resolveMethodSignature(IMethod method) throws JavaModelException { String signature = method.getSignature(); String[] parameterTypes = Signature.getParameterTypes(signature); int length = parameterTypes.length; String[] resolvedParameterTypes = new String[length]; for (int i = 0; i < length; i++) { resolvedParameterTypes[i] = resolveTypeSignature(method, parameterTypes[i]); if (resolvedParameterTypes[i] == null) { return null; } } String resolvedReturnType = resolveTypeSignature(method, Signature.getReturnType(signature)); if (resolvedReturnType == null) { return null; } return Signature.createMethodSignature(resolvedParameterTypes, resolvedReturnType); } /** * Returns the resolved type signature for the given signature in the given * method, or <code>null</code> if unable to resolve. * * @param method method containing the type signature * @param typeSignature the type signature to resolve * @return the resolved type signature * @throws JavaModelException */ private static String resolveTypeSignature(IMethod method, String typeSignature) throws JavaModelException { int count = Signature.getArrayCount(typeSignature); String elementTypeSignature = Signature.getElementType(typeSignature); if (elementTypeSignature.length() == 1) { // no need to resolve primitive types return typeSignature; } String elementTypeName = Signature.toString(elementTypeSignature); IType type = method.getDeclaringType(); String[][] resolvedElementTypeNames = type.resolveType(elementTypeName); if (resolvedElementTypeNames == null || resolvedElementTypeNames.length != 1) { // check if type parameter ITypeParameter typeParameter = method.getTypeParameter(elementTypeName); if (!typeParameter.exists()) { typeParameter = type.getTypeParameter(elementTypeName); } if (typeParameter.exists()) { String[] bounds = typeParameter.getBounds(); if (bounds.length == 0) { return "Ljava/lang/Object;"; //$NON-NLS-1$ } String bound = Signature.createTypeSignature(bounds[0], false); return Signature.createArraySignature(resolveTypeSignature(method, bound), count); } // the type name cannot be resolved return null; } String[] types = resolvedElementTypeNames[0]; types[1] = types[1].replace('.', '$'); String resolvedElementTypeName = Signature.toQualifiedName(types); String resolvedElementTypeSignature = EMPTY_STRING; if (types[0].equals(EMPTY_STRING)) { resolvedElementTypeName = resolvedElementTypeName.substring(1); resolvedElementTypeSignature = Signature.createTypeSignature(resolvedElementTypeName, true); } else { resolvedElementTypeSignature = Signature.createTypeSignature(resolvedElementTypeName, true).replace('.', '/'); } return Signature.createArraySignature(resolvedElementTypeSignature, count); } /** * Returns the resource associated with the specified editor part * @param editor the currently active editor part * @return the corresponding <code>IResource</code> from the editor part */ protected static IResource getResource(IEditorPart editor) { IEditorInput editorInput = editor.getEditorInput(); IResource resource = editorInput.getAdapter(IFile.class); if (resource == null) { resource = ResourcesPlugin.getWorkspace().getRoot(); } return resource; } /** * Returns a handle to the specified method or <code>null</code> if none. * * @param editorPart * the editor containing the method * @param typeName * @param methodName * @param signature * @return handle or <code>null</code> */ protected IMethod getMethodHandle(IEditorPart editorPart, String typeName, String methodName, String signature) throws CoreException { IJavaElement element = editorPart.getEditorInput().getAdapter(IJavaElement.class); IType type = null; if (element instanceof ICompilationUnit) { IType[] types = ((ICompilationUnit) element).getAllTypes(); for (int i = 0; i < types.length; i++) { if (types[i].getFullyQualifiedName().equals(typeName)) { type = types[i]; break; } } } else if (element instanceof IClassFile) { type = ((IClassFile) element).getType(); } if (type != null) { String[] sigs = Signature.getParameterTypes(signature); return type.getMethod(methodName, sigs); } return null; } /** * Returns the <code>IJavaBreakpoint</code> from the specified <code>IMember</code> * @param element the element to get the breakpoint from * @return the current breakpoint from the element or <code>null</code> */ protected IJavaBreakpoint getMethodBreakpoint(IMember element) { IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager(); IBreakpoint[] breakpoints = breakpointManager.getBreakpoints(JDIDebugModel.getPluginIdentifier()); if (element instanceof IMethod) { IMethod method = (IMethod) element; for (int i = 0; i < breakpoints.length; i++) { IBreakpoint breakpoint = breakpoints[i]; if (breakpoint instanceof IJavaMethodBreakpoint) { IJavaMethodBreakpoint methodBreakpoint = (IJavaMethodBreakpoint) breakpoint; IMember container = null; try { container = BreakpointUtils.getMember(methodBreakpoint); } catch (CoreException e) { JDIDebugUIPlugin.log(e); return null; } if (container == null) { try { if (method.getDeclaringType().getFullyQualifiedName().equals(methodBreakpoint.getTypeName()) && method.getElementName().equals(methodBreakpoint.getMethodName()) && methodBreakpoint.getMethodSignature().equals(resolveMethodSignature(method))) { return methodBreakpoint; } } catch (CoreException e) { JDIDebugUIPlugin.log(e); } } else { if (container instanceof IMethod) { if (method.getDeclaringType().getFullyQualifiedName().equals(container.getDeclaringType().getFullyQualifiedName())) { if (method.isSimilar((IMethod) container)) { return methodBreakpoint; } } } } } } } return null; } /** * Returns the compilation unit from the editor * @param editor the editor to get the compilation unit from * @return the compilation unit or <code>null</code> */ protected CompilationUnit parseCompilationUnit(ITextEditor editor) { return parseCompilationUnit(getTypeRoot(editor.getEditorInput())); } /** * Parses the {@link ITypeRoot}. * @param root the root * @return the parsed {@link CompilationUnit} */ CompilationUnit parseCompilationUnit(ITypeRoot root) { if(root != null) { return SharedASTProvider.getAST(root, SharedASTProvider.WAIT_YES, null); } return null; } /* * (non-Javadoc) * * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleWatchpoints(org.eclipse.ui.IWorkbenchPart, * org.eclipse.jface.viewers.ISelection) */ @Override public boolean canToggleWatchpoints(IWorkbenchPart part, ISelection selection) { if (isRemote(part, selection)) { return false; } if (selection instanceof IStructuredSelection) { IStructuredSelection ss = (IStructuredSelection) selection; return isFields(ss); } return (selection instanceof ITextSelection) && isField((ITextSelection) selection, part); } /** * Returns a selection of the member in the given text selection, or the * original selection if none. * * @param part * @param selection * @return a structured selection of the member in the given text selection, * or the original selection if none * @exception CoreException * if an exception occurs */ protected ISelection translateToMembers(IWorkbenchPart part, ISelection selection) throws CoreException { ITextEditor textEditor = getTextEditor(part); if (textEditor != null && selection instanceof ITextSelection) { ITextSelection textSelection = (ITextSelection) selection; IEditorInput editorInput = textEditor.getEditorInput(); IDocumentProvider documentProvider = textEditor.getDocumentProvider(); if (documentProvider == null) { throw new CoreException(Status.CANCEL_STATUS); } IDocument document = documentProvider.getDocument(editorInput); int offset = textSelection.getOffset(); if (document != null) { try { IRegion region = document.getLineInformationOfOffset(offset); int end = region.getOffset() + region.getLength(); while (Character.isWhitespace(document.getChar(offset)) && offset < end) { offset++; } } catch (BadLocationException e) {} } IMember m = null; ITypeRoot root = getTypeRoot(editorInput); if(root instanceof ICompilationUnit) { ICompilationUnit unit = (ICompilationUnit) root; synchronized (unit) { unit.reconcile(ICompilationUnit.NO_AST , false, null, null); } } if(root != null){ IJavaElement e = root.getElementAt(offset); if (e instanceof IMember) { m = (IMember) e; } } if (m != null) { return new StructuredSelection(m); } } return selection; } /** * Returns the {@link ITypeRoot} for the given {@link IEditorInput} * @param input * @return the type root or <code>null</code> if one cannot be derived * @since 3.4 */ private ITypeRoot getTypeRoot(IEditorInput input) { ITypeRoot root = input.getAdapter(IClassFile.class); if(root == null) { IWorkingCopyManager manager = JavaUI.getWorkingCopyManager(); root = manager.getWorkingCopy(input); } if(root == null) { root = DebugWorkingCopyManager.getWorkingCopy(input, false); } return root; } /** * Return the associated IField (Java model) for the given * IJavaFieldVariable (JDI model) */ private IField getField(IJavaFieldVariable variable) throws CoreException { String varName = null; try { varName = variable.getName(); } catch (DebugException x) { JDIDebugUIPlugin.log(x); return null; } IField field; IJavaType declaringType = variable.getDeclaringType(); IType type = JavaDebugUtils.resolveType(declaringType); if (type != null) { field = type.getField(varName); if (field.exists()) { return field; } } return null; } /* * (non-Javadoc) * * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension#toggleBreakpoints(org.eclipse.ui.IWorkbenchPart, * org.eclipse.jface.viewers.ISelection) */ @Override public void toggleBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { ISelection sel = translateToMembers(part, selection); if(sel instanceof IStructuredSelection) { IMember member = (IMember) ((IStructuredSelection)sel).getFirstElement(); int mtype = member.getElementType(); if(mtype == IJavaElement.FIELD || mtype == IJavaElement.METHOD || mtype == IJavaElement.INITIALIZER) { // remove line breakpoint if present first if (selection instanceof ITextSelection) { ITextSelection ts = (ITextSelection) selection; IJavaLineBreakpoint breakpoint = null; ITextEditor editor = getTextEditor(part); IAnnotationModel annotationModel = editor.getDocumentProvider().getAnnotationModel(editor.getEditorInput()); IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput()); if (annotationModel != null) { Iterator<Annotation> iterator = annotationModel.getAnnotationIterator(); while (iterator.hasNext()) { Object object = iterator.next(); if (object instanceof SimpleMarkerAnnotation) { SimpleMarkerAnnotation markerAnnotation = (SimpleMarkerAnnotation) object; IMarker marker = markerAnnotation.getMarker(); try { if (marker.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) { Position position = annotationModel.getPosition(markerAnnotation); int line = document.getLineOfOffset(position.getOffset()); if (line == ts.getStartLine()) { IBreakpoint oldBreakpoint = DebugPlugin.getDefault().getBreakpointManager().getBreakpoint(marker); if (oldBreakpoint instanceof IJavaLineBreakpoint) { breakpoint = (IJavaLineBreakpoint) oldBreakpoint; break; } } } } catch (BadLocationException e) { JDIDebugUIPlugin.log(e); } } } } if (breakpoint != null) { if (BreakpointToggleUtils.isToggleTracepoints()) { deleteTracepoint(breakpoint, part, null); BreakpointToggleUtils.setUnsetTracepoints(false); } else { deleteBreakpoint(breakpoint, part, null); } return; } CompilationUnit unit = parseCompilationUnit(getTextEditor(part)); ValidBreakpointLocationLocator loc = new ValidBreakpointLocationLocator(unit, ts.getStartLine()+1, true, true); unit.accept(loc); if(loc.getLocationType() == ValidBreakpointLocationLocator.LOCATION_METHOD) { toggleMethodBreakpoints(part, ts); } else if(loc.getLocationType() == ValidBreakpointLocationLocator.LOCATION_FIELD) { if (BreakpointToggleUtils.isToggleTracepoints()) { BreakpointToggleUtils.report(ActionMessages.TracepointToggleAction_Unavailable, part); BreakpointToggleUtils.setUnsetTracepoints(false); return; } toggleWatchpoints(part, ts); } else if(loc.getLocationType() == ValidBreakpointLocationLocator.LOCATION_LINE) { toggleLineBreakpoints(part, ts, false, loc); } } } else if(member.getElementType() == IJavaElement.TYPE) { if (BreakpointToggleUtils.isToggleTracepoints()) { BreakpointToggleUtils.report(ActionMessages.TracepointToggleAction_Unavailable, part); BreakpointToggleUtils.setUnsetTracepoints(false); return; } toggleClassBreakpoints(part, sel); } else { //fall back to old behavior, always create a line breakpoint toggleLineBreakpoints(part, selection, true, null); } } } /** * Deletes the given breakpoint using the operation history, which allows to undo the deletion. * * @param breakpoint the breakpoint to delete * @param part a workbench part, or <code>null</code> if unknown * @param progressMonitor the progress monitor * @throws CoreException if the deletion fails */ private static void deleteBreakpoint(IJavaBreakpoint breakpoint, IWorkbenchPart part, IProgressMonitor monitor) throws CoreException { final Shell shell = part != null ? part.getSite().getShell() : null; final boolean[] result = new boolean[] { true }; final IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(JDIDebugUIPlugin.getUniqueIdentifier()); boolean prompt = prefs.getBoolean(IJDIPreferencesConstants.PREF_PROMPT_DELETE_CONDITIONAL_BREAKPOINT, true); if (prompt && breakpoint instanceof IJavaLineBreakpoint && ((IJavaLineBreakpoint) breakpoint).getCondition() != null) { Display display = shell != null && !shell.isDisposed() ? shell.getDisplay() : PlatformUI.getWorkbench().getDisplay(); if (!display.isDisposed()) { display.syncExec(new Runnable() { @Override public void run() { MessageDialogWithToggle dialog = MessageDialogWithToggle.openOkCancelConfirm(shell, ActionMessages.ToggleBreakpointAdapter_confirmDeleteTitle, ActionMessages.ToggleBreakpointAdapter_confirmDeleteMessage, ActionMessages.ToggleBreakpointAdapter_confirmDeleteShowAgain, false, null, null); if (dialog.getToggleState()) { prefs.putBoolean(IJDIPreferencesConstants.PREF_PROMPT_DELETE_CONDITIONAL_BREAKPOINT, false); } result[0] = dialog.getReturnCode() == IDialogConstants.OK_ID; } }); } } if (result[0]) { DebugUITools.deleteBreakpoints(new IBreakpoint[] { breakpoint }, shell, monitor); } } private static void deleteTracepoint(IJavaBreakpoint breakpoint, IWorkbenchPart part, IProgressMonitor monitor) throws CoreException { final Shell shell = part != null ? part.getSite().getShell() : null; final boolean[] result = new boolean[] { true }; final IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(JDIDebugUIPlugin.getUniqueIdentifier()); boolean prompt = prefs.getBoolean(IJDIPreferencesConstants.PREF_PROMPT_DELETE_CONDITIONAL_BREAKPOINT, true); if (prompt && breakpoint instanceof IJavaLineBreakpoint) { String condition = ((IJavaLineBreakpoint) breakpoint).getCondition(); boolean conditionChanged = true; if (condition != null) { int index = condition.indexOf(";"); //$NON-NLS-1$ if (index != -1) { int lastIndex = condition.lastIndexOf(";"); //$NON-NLS-1$ if (index == lastIndex) { conditionChanged = false; } } else { if (condition.indexOf("print") != -1) { //$NON-NLS-1$ conditionChanged = false; } } } if (conditionChanged && condition != null) { Display display = shell != null && !shell.isDisposed() ? shell.getDisplay() : PlatformUI.getWorkbench().getDisplay(); if (!display.isDisposed()) { display.syncExec(new Runnable() { @Override public void run() { MessageDialogWithToggle dialog = MessageDialogWithToggle.openOkCancelConfirm(shell, ActionMessages.ToggleBreakpointAdapter_confirmDeleteTitle, ActionMessages.ToggleBreakpointAdapter_confirmDeleteMessage, ActionMessages.ToggleBreakpointAdapter_confirmDeleteShowAgain, false, null, null); if (dialog.getToggleState()) { prefs.putBoolean(IJDIPreferencesConstants.PREF_PROMPT_DELETE_CONDITIONAL_BREAKPOINT, false); } result[0] = dialog.getReturnCode() == IDialogConstants.OK_ID; } }); } } } if (result[0]) { DebugUITools.deleteBreakpoints(new IBreakpoint[] { breakpoint }, shell, monitor); } } /* * (non-Javadoc) * * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension#canToggleBreakpoints(org.eclipse.ui.IWorkbenchPart, * org.eclipse.jface.viewers.ISelection) */ @Override public boolean canToggleBreakpoints(IWorkbenchPart part, ISelection selection) { if (isRemote(part, selection)) { return false; } return canToggleLineBreakpoints(part, selection); } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension2#toggleBreakpointsWithEvent(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection, org.eclipse.swt.widgets.Event) */ @Override public void toggleBreakpointsWithEvent(IWorkbenchPart part, ISelection selection, Event event) throws CoreException { if(event != null) { if((event.stateMask & SWT.MOD2) > 0) { ITextEditor editor = getTextEditor(part); if(editor != null) { IVerticalRulerInfo info = editor.getAdapter(IVerticalRulerInfo.class); if(info != null) { IBreakpoint bp = BreakpointUtils.getBreakpointFromEditor(editor, info); if(bp != null) { bp.setEnabled(!bp.isEnabled()); return; } } } } else if((event.stateMask & SWT.MOD1) > 0) { ITextEditor editor = getTextEditor(part); if(editor != null) { IVerticalRulerInfo info = editor.getAdapter(IVerticalRulerInfo.class); if(info != null) { IBreakpoint bp = BreakpointUtils.getBreakpointFromEditor(editor, info); if(bp != null) { PreferencesUtil.createPropertyDialogOn( editor.getSite().getShell(), bp, null, null, null).open(); return; } } } } } toggleBreakpoints(part, selection); } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension2#canToggleBreakpointsWithEvent(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection, org.eclipse.swt.widgets.Event) */ @Override public boolean canToggleBreakpointsWithEvent(IWorkbenchPart part, ISelection selection, Event event) { return canToggleBreakpoints(part, selection); } /** * Returns the {@link ITypeRoot} for the given {@link IEditorInput} * * @param input * @return the type root or <code>null</code> if one cannot be derived * @since 3.8 */ private String getCodeTemplate(ITextSelection textSelection, CompilationUnitEditor part) { TemplateContextType contextType = JavaPlugin.getDefault().getTemplateContextRegistry().getContextType(JavaContextType.ID_STATEMENTS); TemplateEngine fStatementEngine = new TemplateEngine(contextType); fStatementEngine.reset(); ITextViewer viewer = part.getViewer(); final String[] fTemplateBuffer = new String[1]; fTemplateBuffer[0] = null; if (viewer != null) { Display.getDefault().syncExec(new Runnable() { @Override public void run() { ITextEditor editor = getTextEditor(part); if (editor != null) { IJavaElement element = getJavaElement(editor.getEditorInput()); ICompilationUnit cunit = null; IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IFile file = root.getFile(element.getPath()); cunit = JavaCore.createCompilationUnitFrom(file); IDocumentProvider documentProvider = editor.getDocumentProvider(); if (documentProvider == null) { return; } IDocument document = documentProvider.getDocument(editor.getEditorInput()); try { IRegion line = document.getLineInformation(textSelection.getStartLine() + 1); Point selectedRange = viewer.getSelectedRange(); viewer.setSelectedRange(selectedRange.x, 0); fStatementEngine.complete(viewer, line.getOffset(), cunit); viewer.setSelectedRange(selectedRange.x, selectedRange.y); TemplateProposal[] templateProposals = fStatementEngine.getResults(); for (TemplateProposal templateProposal : templateProposals) { Template template = templateProposal.getTemplate(); if (template.getName().equals("systrace")) { //$NON-NLS-1$ CompilationUnitContextType contextType = (CompilationUnitContextType) JavaPlugin.getDefault().getTemplateContextRegistry().getContextType(template.getContextTypeId()); CompilationUnitContext context = contextType.createContext(document, line.getOffset(), 0, cunit); context.setVariable("selection", EMPTY_STRING); //$NON-NLS-1$ context.setForceEvaluation(true); fTemplateBuffer[0] = context.evaluate(template).getString(); return; } } } catch (BadLocationException | TemplateException e) { // ignore } } } }); } return fTemplateBuffer[0]; } }