diff --git a/php/php.dbgp/licenseinfo.xml b/php/php.dbgp/licenseinfo.xml index bc743279315b..e2e85deceec8 100644 --- a/php/php.dbgp/licenseinfo.xml +++ b/php/php.dbgp/licenseinfo.xml @@ -21,7 +21,9 @@ --> + src/org/netbeans/modules/php/dbgp/resources/class.png src/org/netbeans/modules/php/dbgp/resources/notice-glyph.gif + src/org/netbeans/modules/php/dbgp/resources/php16Key.png src/org/netbeans/modules/php/dbgp/resources/undefined.gif diff --git a/php/php.dbgp/nbproject/project.xml b/php/php.dbgp/nbproject/project.xml index 52a807057991..f5f5b12b9324 100644 --- a/php/php.dbgp/nbproject/project.xml +++ b/php/php.dbgp/nbproject/project.xml @@ -87,6 +87,15 @@ 1.58 + + org.netbeans.modules.editor.completion + + + + 1 + 1.67 + + org.netbeans.modules.editor.document @@ -149,6 +158,14 @@ 9.0 + + org.netbeans.modules.parsing.indexing + + + + 9.31 + + org.netbeans.modules.php.api.executable diff --git a/php/php.dbgp/src/META-INF/debugger/org.netbeans.spi.debugger.ui.BreakpointType b/php/php.dbgp/src/META-INF/debugger/org.netbeans.spi.debugger.ui.BreakpointType index 11de7f04d4b2..f5d02c2d8317 100644 --- a/php/php.dbgp/src/META-INF/debugger/org.netbeans.spi.debugger.ui.BreakpointType +++ b/php/php.dbgp/src/META-INF/debugger/org.netbeans.spi.debugger.ui.BreakpointType @@ -1 +1,2 @@ org.netbeans.modules.php.dbgp.breakpoints.DbgpFunctionBreakpointType +org.netbeans.modules.php.dbgp.breakpoints.DbgpExceptionBreakpointType diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointModel.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointModel.java index 339522e91ab9..aea90c868465 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointModel.java +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointModel.java @@ -50,6 +50,7 @@ public class BreakpointModel extends ViewModelSupport implements NodeModel { public static final String DISABLED_LINE_CONDITIONAL_BREAKPOINT = "org/netbeans/modules/debugger/resources/breakpointsView/DisabledConditionalBreakpoint"; // NOI18N public static final String BROKEN_LINE_BREAKPOINT = "org/netbeans/modules/debugger/resources/breakpointsView/Breakpoint_broken"; // NOI18N private static final String METHOD = "TXT_Method"; // NOI18N + private static final String EXCEPTION = "TXT_Exception"; // NOI18N private static final String PARENS = "()"; // NOI18N private final Map myCurrentBreakpoints; @@ -74,6 +75,12 @@ public String getDisplayName(Object node) throws UnknownTypeException { builder.append(breakpoint.getFunction()); builder.append(PARENS); return builder.toString(); + } else if (node instanceof ExceptionBreakpoint) { + ExceptionBreakpoint breakpoint = (ExceptionBreakpoint) node; + StringBuilder builder = new StringBuilder(NbBundle.getMessage(BreakpointModel.class, EXCEPTION)); + builder.append(" "); // NOI18N + builder.append(breakpoint.getException()); + return builder.toString(); } throw new UnknownTypeException(node); } @@ -119,15 +126,25 @@ public String getShortDescription(Object node) throws UnknownTypeException { public void setCurrentStack(Stack stack, DebugSession session) { if (stack == null) { - synchronized (myCurrentBreakpoints) { - AbstractBreakpoint breakpoint = myCurrentBreakpoints.remove(session); - fireChangeEvent(new ModelEvent.NodeChanged(this, breakpoint)); - } + removeCurrentBreakpoint(session); return; } String currentCommand = stack.getCurrentCommandName(); if (!foundLineBreakpoint(stack.getFileName().replace("file:///", "file:/"), stack.getLine() - 1, session)) { //NOI18N - foundFunctionBreakpoint(currentCommand, session); + if (!foundFunctionBreakpoint(currentCommand, session)) { + /** + * Clear myCurrentBreakpoints because if the current breakpoints is not found, + * the previous breakpoint will still be shown as current + */ + removeCurrentBreakpoint(session); + } + } + } + + private void removeCurrentBreakpoint(DebugSession session) { + synchronized (myCurrentBreakpoints) { + AbstractBreakpoint breakpoint = myCurrentBreakpoints.remove(session); + fireChangeEvent(new ModelEvent.NodeChanged(this, breakpoint)); } } @@ -216,5 +233,4 @@ public boolean accept(Breakpoint breakpoint) { } } - } diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointRuntimeSetter.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointRuntimeSetter.java index 8871164ef397..3c38c12bc4d4 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointRuntimeSetter.java +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointRuntimeSetter.java @@ -66,7 +66,12 @@ public void propertyChange(PropertyChangeEvent event) { return; } Object source = event.getSource(); - performCommand((Breakpoint) source, Lazy.UPDATE_COMMAND); + + if (((Breakpoint) source).isEnabled()) { + performCommand((Breakpoint) source, Lazy.SET_COMMAND); + } else { + performCommand((Breakpoint) source, Lazy.REMOVE_COMMAND); + } } private void performCommand(Breakpoint breakpoint, Command command) { diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointsReader.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointsReader.java index 4962e0bb1ce4..890276a1db36 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointsReader.java +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointsReader.java @@ -32,17 +32,20 @@ */ public class BreakpointsReader implements Properties.Reader { - private static final String ENABED = "enabled"; // NOI18N + private static final String ENABLED = "enabled"; // NOI18N private static final String FUNC_NAME = "functionName"; // NOI18N + private static final String EXCEPTION_NAME = "exceptionName"; // NOI18N private static final String TYPE = "type"; // NOI18N private static final String GROUP_NAME = "groupName"; // NOI18N + private static final String[] SUPPORTED_CLASS_NAMES = new String[] { + LineBreakpoint.class.getName(), + FunctionBreakpoint.class.getName(), + ExceptionBreakpoint.class.getName() + }; @Override public String[] getSupportedClassNames() { - return new String[]{ - LineBreakpoint.class.getName(), - FunctionBreakpoint.class.getName() - }; + return SUPPORTED_CLASS_NAMES; } @Override @@ -53,7 +56,7 @@ public Object read(String typeID, Properties properties) { return null; } LineBreakpoint breakpoint = new LineBreakpoint(line); - if (!properties.getBoolean(ENABED, true)) { + if (!properties.getBoolean(ENABLED, true)) { breakpoint.disable(); } breakpoint.setGroupName(properties.getString(GROUP_NAME, "")); @@ -66,11 +69,19 @@ public Object read(String typeID, Properties properties) { return null; } FunctionBreakpoint breakpoint = new FunctionBreakpoint(type, func); - if (!properties.getBoolean(ENABED, true)) { + if (!properties.getBoolean(ENABLED, true)) { breakpoint.disable(); } breakpoint.setGroupName(properties.getString(GROUP_NAME, "")); return breakpoint; + } else if (typeID.equals(ExceptionBreakpoint.class.getName())) { + String exception = properties.getString(EXCEPTION_NAME, null); + ExceptionBreakpoint breakpoint = new ExceptionBreakpoint(exception); + if (!properties.getBoolean(ENABLED, true)) { + breakpoint.disable(); + } + breakpoint.setGroupName(properties.getString(GROUP_NAME, "")); // NOI18N + return breakpoint; } else { return null; } @@ -83,7 +94,7 @@ public void write(Object object, Properties properties) { FileObject fileObject = breakpoint.getLine().getLookup().lookup(FileObject.class); properties.setString(LineBreakpoint.PROP_URL, fileObject.toURL().toString()); properties.setInt(LineBreakpoint.PROP_LINE_NUMBER, breakpoint.getLine().getLineNumber()); - properties.setBoolean(ENABED, breakpoint.isEnabled()); + properties.setBoolean(ENABLED, breakpoint.isEnabled()); properties.setString(GROUP_NAME, breakpoint.getGroupName()); properties.setString(LineBreakpoint.PROP_CONDITION, breakpoint.getCondition()); } else if (object instanceof FunctionBreakpoint) { @@ -91,7 +102,13 @@ public void write(Object object, Properties properties) { String func = breakpoint.getFunction(); properties.setString(FUNC_NAME, func); properties.setString(TYPE, breakpoint.getType().toString()); - properties.setBoolean(ENABED, breakpoint.isEnabled()); + properties.setBoolean(ENABLED, breakpoint.isEnabled()); + properties.setString(GROUP_NAME, breakpoint.getGroupName()); + } else if (object instanceof ExceptionBreakpoint) { + ExceptionBreakpoint breakpoint = (ExceptionBreakpoint) object; + String exception = breakpoint.getException(); + properties.setString(EXCEPTION_NAME, exception); + properties.setBoolean(ENABLED, breakpoint.isEnabled()); properties.setString(GROUP_NAME, breakpoint.getGroupName()); } } diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Bundle.properties b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Bundle.properties index 21466d838224..17c84b653e01 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Bundle.properties +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Bundle.properties @@ -35,3 +35,4 @@ LBL_PhpType=PHP LBL_MethodBreakpointType=Method TXT_Method=Method +TXT_Exception=Exception diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/DbgpExceptionBreakpointType.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/DbgpExceptionBreakpointType.java new file mode 100644 index 000000000000..77bdcfffa825 --- /dev/null +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/DbgpExceptionBreakpointType.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.php.dbgp.breakpoints; + +import javax.swing.JComponent; +import javax.swing.text.JTextComponent; +import org.netbeans.api.editor.EditorRegistry; +import org.netbeans.modules.editor.NbEditorUtilities; +import org.netbeans.modules.php.api.util.FileUtils; + +import org.netbeans.modules.php.dbgp.ui.DbgpExceptionBreakpointPanel; +import org.netbeans.spi.debugger.ui.BreakpointType; +import org.openide.filesystems.FileObject; +import org.openide.util.NbBundle; + +@NbBundle.Messages({ + "DbgpExceptionBreakpointType.CategoryDisplayName=PHP", + "DbgpExceptionBreakpointType.TypeDisplayName=Exception" +}) +public class DbgpExceptionBreakpointType extends BreakpointType { + + @Override + public String getCategoryDisplayName() { + return Bundle.DbgpExceptionBreakpointType_CategoryDisplayName(); + } + + @Override + public JComponent getCustomizer() { + return new DbgpExceptionBreakpointPanel(); + } + + @Override + public String getTypeDisplayName() { + return Bundle.DbgpExceptionBreakpointType_TypeDisplayName(); + } + + @Override + public boolean isDefault() { + JTextComponent lastFocusedComponent = EditorRegistry.lastFocusedComponent(); + if (lastFocusedComponent == null) { + return false; + } + FileObject fileObject = NbEditorUtilities.getFileObject(lastFocusedComponent.getDocument()); + if (fileObject == null) { + return false; + } + return FileUtils.isPhpFile(fileObject); + } + +} diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/ExceptionBreakpoint.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/ExceptionBreakpoint.java new file mode 100644 index 000000000000..0c421ef92e71 --- /dev/null +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/ExceptionBreakpoint.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.php.dbgp.breakpoints; + +import org.netbeans.modules.php.dbgp.DebugSession; + +/** + * Represent breakpoint for exceptions. + * + * + */ +public class ExceptionBreakpoint extends AbstractBreakpoint { + private final String exceptionName; + + public ExceptionBreakpoint(String exceptionName) { + this.exceptionName = exceptionName; + } + + public String getException() { + return exceptionName; + } + + @Override + public boolean isSessionRelated(DebugSession session) { + return true; + } + +} diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Utils.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Utils.java index bc291dcfdb80..a247241a34cc 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Utils.java +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Utils.java @@ -128,6 +128,9 @@ public static BrkpntSetCommand getCommand(DebugSession session, SessionId id, Ab } else { assert false; } + } else if (breakpoint instanceof ExceptionBreakpoint) { + ExceptionBreakpoint exceptionBreakpoint = (ExceptionBreakpoint) breakpoint; + command = BrkpntCommandBuilder.buildExceptionBreakpoint(session.getTransactionId(), exceptionBreakpoint); } if (command == null) { breakpoint.setInvalid(); // No command, can not be valid diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntCommandBuilder.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntCommandBuilder.java index 07a2f28dfbdc..5e8e51c90b46 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntCommandBuilder.java +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntCommandBuilder.java @@ -19,6 +19,7 @@ package org.netbeans.modules.php.dbgp.packets; import org.netbeans.modules.php.dbgp.SessionId; +import org.netbeans.modules.php.dbgp.breakpoints.ExceptionBreakpoint; import org.netbeans.modules.php.dbgp.breakpoints.FunctionBreakpoint; import org.netbeans.modules.php.dbgp.breakpoints.LineBreakpoint; import org.netbeans.modules.php.dbgp.packets.BrkpntSetCommand.Types; @@ -100,6 +101,13 @@ public static BrkpntSetCommand buildExceptionBreakpoint(String transactionId, St return command; } + public static BrkpntSetCommand buildExceptionBreakpoint(String transactionId, ExceptionBreakpoint exceptionBreakpoint) { + String exceptionName = exceptionBreakpoint.getException(); + BrkpntSetCommand command = buildExceptionBreakpoint(transactionId, exceptionName); + command.setBreakpoint(exceptionBreakpoint); + return command; + } + public static BrkpntSetCommand buildConditionalBreakpoint(String transactionId, String expression) { BrkpntSetCommand command = new BrkpntSetCommand(transactionId); command.setType(Types.WATCH); diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntSetCommand.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntSetCommand.java index 1bdbced42a87..b0edacd7bb2e 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntSetCommand.java +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntSetCommand.java @@ -33,7 +33,7 @@ public class BrkpntSetCommand extends DbgpCommand { private static final String STATE_ARG = "-s "; // NOI18N private static final String TEMP_ARG = "-r "; // NOI18N private static final String FUNC_ARG = "-m "; // NOI18N - private static final String EXCEPTION_ARG = "-x"; // NOI18N + private static final String EXCEPTION_ARG = "-x "; // NOI18N private String myFunction; private Types myType; private String myFile; diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/InitMessage.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/InitMessage.java index c68ddde0833a..426de514213b 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/InitMessage.java +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/InitMessage.java @@ -122,7 +122,11 @@ private void setBreakpoints(DebugSession session) { SessionId id = session.getSessionId(); Breakpoint[] breakpoints = DebuggerManager.getDebuggerManager().getBreakpoints(); for (Breakpoint breakpoint : breakpoints) { - if (!(breakpoint instanceof AbstractBreakpoint)) { + if (!(breakpoint instanceof AbstractBreakpoint) ) { + continue; + } + //do not set a breakpoint at debug start if it is not enabled + if (!breakpoint.isEnabled()) { continue; } AbstractBreakpoint brkpnt = (AbstractBreakpoint) breakpoint; diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/resources/class.png b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/resources/class.png new file mode 100644 index 000000000000..220e6f385e0a Binary files /dev/null and b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/resources/class.png differ diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/resources/layer.xml b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/resources/layer.xml index 0e1261e3b7ed..7b2f67179c4f 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/resources/layer.xml +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/resources/layer.xml @@ -48,6 +48,12 @@ + + + + + diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/resources/php16Key.png b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/resources/php16Key.png new file mode 100644 index 000000000000..4cf41724a8f8 Binary files /dev/null and b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/resources/php16Key.png differ diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/Bundle.properties b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/Bundle.properties index f500731c8883..5552c62af6ad 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/Bundle.properties +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/Bundle.properties @@ -70,3 +70,6 @@ DbgpLineBreakpointCustomizerPanel.fileTextField.text= DbgpLineBreakpointCustomizerPanel.lineNumberLabel.text=&Line Number: DbgpLineBreakpointCustomizerPanel.fileLabel.text=&File: DbgpLineBreakpointCustomizerPanel.conditionComboBox.toolTipText=Breakpoint is hit when this condition evaluates to true. +LBL_ExceptionName=&Exception Name: +DbgpExceptionBreakpointPanel.exceptionLabel.AccessibleContext.accessibleDescription=Label for exception name +DbgpExceptionBreakpointPanel.exceptionLabel.AccessibleContext.accessibleName=Exception Name diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpExceptionBreakpointPanel.form b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpExceptionBreakpointPanel.form new file mode 100644 index 000000000000..759e6284038f --- /dev/null +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpExceptionBreakpointPanel.form @@ -0,0 +1,101 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpExceptionBreakpointPanel.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpExceptionBreakpointPanel.java new file mode 100644 index 000000000000..a6ccf881980f --- /dev/null +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpExceptionBreakpointPanel.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.php.dbgp.ui; + +import javax.swing.JComponent; +import javax.swing.JEditorPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.editor.Utilities; +import org.netbeans.modules.php.dbgp.breakpoints.ExceptionBreakpoint; +import org.netbeans.modules.php.dbgp.ui.completion.ExceptionClassNbDebugEditorKit; +import org.netbeans.spi.debugger.ui.Controller; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.util.NbBundle; +import org.openide.util.Pair; + +@NbBundle.Messages({ + "DbgpExceptionBreakpointPanel.EmptyExceptionName=Please enter non-empty exception name.", +}) +public class DbgpExceptionBreakpointPanel extends JPanel implements Controller { + private static final long serialVersionUID = 4967178020173186468L; + + private final JEditorPane classNameEditorPane; + private final JScrollPane classNameScrollPane; + + public DbgpExceptionBreakpointPanel() { + initComponents(); + Pair codeCompletionEditor = createCodeCompletionEditor(); + classNameScrollPane = codeCompletionEditor.first(); + classNameEditorPane = codeCompletionEditor.second(); + classNameEditorPane.getAccessibleContext().setAccessibleName("exception class name input field"); // NOI18N + classNameEditorPane.getAccessibleContext().setAccessibleDescription("field for input of the exception class name for the exception breakpoint"); // NOI18N + exceptionLabel.setLabelFor(classNameScrollPane); + } + + @Override + public boolean cancel() { + return true; + } + + @Override + public boolean ok() { + String exceptionName = classNameEditorPane.getText(); + if (exceptionName == null || exceptionName.trim().length() == 0) { + String msg = Bundle.DbgpExceptionBreakpointPanel_EmptyExceptionName(); + NotifyDescriptor descr = new NotifyDescriptor.Message(msg); + DialogDisplayer.getDefault().notify(descr); + return false; + } + ExceptionBreakpoint breakpoint = new ExceptionBreakpoint(exceptionName); + DebuggerManager.getDebuggerManager().addBreakpoint(breakpoint); + return true; + } + + private Pair createCodeCompletionEditor() { + JComponent [] editorComponents = Utilities.createSingleLineEditor(ExceptionClassNbDebugEditorKit.MIME_TYPE); + JScrollPane scrollPane = (JScrollPane) editorComponents[0]; + JEditorPane editorPane = (JEditorPane) editorComponents[1]; + initClassNameEditorPanel(scrollPane); + editorPane.setText(""); // NOI18N + scrollPane.setToolTipText(""); // NOI18N + editorPane.setToolTipText(""); // NOI18N + return Pair.of(scrollPane, editorPane); + } + + private void initClassNameEditorPanel(JScrollPane scrollPane) { + java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.BASELINE; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3); + classNameEditorPanel.add(scrollPane, gridBagConstraints); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + classNameEditorPanel = new javax.swing.JPanel(); + exceptionLabel = new javax.swing.JLabel(); + + setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(DbgpExceptionBreakpointPanel.class, "LBL_Settings"))); // NOI18N + + classNameEditorPanel.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(exceptionLabel, org.openide.util.NbBundle.getMessage(DbgpExceptionBreakpointPanel.class, "LBL_ExceptionName")); // NOI18N + exceptionLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; + gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3); + classNameEditorPanel.add(exceptionLabel, gridBagConstraints); + exceptionLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(DbgpExceptionBreakpointPanel.class, "DbgpExceptionBreakpointPanel.exceptionLabel.AccessibleContext.accessibleName")); // NOI18N + exceptionLabel.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(DbgpExceptionBreakpointPanel.class, "DbgpExceptionBreakpointPanel.exceptionLabel.AccessibleContext.accessibleDescription")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(classNameEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 361, Short.MAX_VALUE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(classNameEditorPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + + classNameEditorPanel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(DbgpExceptionBreakpointPanel.class, "A11_SettingsName")); // NOI18N + + getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(DbgpExceptionBreakpointPanel.class, "A11_SettingsName")); // NOI18N + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel classNameEditorPanel; + private javax.swing.JLabel exceptionLabel; + // End of variables declaration//GEN-END:variables +} diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionClassNbDebugEditorKit.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionClassNbDebugEditorKit.java new file mode 100644 index 000000000000..d9a8f16b587f --- /dev/null +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionClassNbDebugEditorKit.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.php.dbgp.ui.completion; + +import org.netbeans.modules.editor.NbEditorKit; + +public class ExceptionClassNbDebugEditorKit extends NbEditorKit { + + public static final String MIME_TYPE = "text/x-php-nbdebug-class-exception"; // NOI18N + + @Override + public String getContentType() { + return MIME_TYPE; + } +} diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionCompletionItem.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionCompletionItem.java new file mode 100644 index 000000000000..fb4bfa39f9d2 --- /dev/null +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionCompletionItem.java @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.php.dbgp.ui.completion; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.event.KeyEvent; +import javax.swing.ImageIcon; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import org.netbeans.api.annotations.common.StaticResource; +import org.netbeans.api.editor.completion.Completion; +import org.netbeans.modules.php.editor.api.elements.ClassElement; +import org.netbeans.modules.php.editor.api.elements.PhpElement; +import org.netbeans.spi.editor.completion.CompletionItem; +import org.netbeans.spi.editor.completion.CompletionTask; +import org.netbeans.spi.editor.completion.support.CompletionUtilities; +import org.openide.util.Exceptions; +import org.openide.util.ImageUtilities; + +public class ExceptionCompletionItem implements CompletionItem { + + @StaticResource + private static final String CLASS_ICON = "org/netbeans/modules/php/dbgp/resources/class.png"; // NOI18N + + @StaticResource + private static final String PLATFORM_ICON = "org/netbeans/modules/php/dbgp/resources/php16Key.png"; // NOI18N + + private final ClassElement element; + private final boolean isPlatform; + private final boolean isDeprecated; + + public ExceptionCompletionItem(ClassElement element) { + this.element = element; + if (element instanceof ClassElement) { + isPlatform = element.isPlatform(); + isDeprecated = element.isDeprecated(); + } else { + isPlatform = false; + isDeprecated = false; + } + } + + @Override + public void defaultAction(JTextComponent component) { + Document doc = component.getDocument(); + try { + doc.remove(0, doc.getLength()); + doc.insertString(0, getName(), null); + } catch (BadLocationException ex) { + Exceptions.printStackTrace(ex); + } + Completion.get().hideAll(); + } + + @Override + public void processKeyEvent(KeyEvent evt) { + } + + @Override + public int getPreferredWidth(Graphics g, Font defaultFont) { + return CompletionUtilities.getPreferredWidth(getLeftText(), getRightText(), g, defaultFont); + } + + @Override + public void render(Graphics g, Font defaultFont, Color defaultColor, Color backgroundColor, int width, int height, boolean selected) { + ImageIcon icon = ImageUtilities.loadImageIcon(getIcon(), false); + + CompletionUtilities.renderHtml(icon, getLeftText(), getRightText(), g, defaultFont, + Color.black, width, height, selected); + } + + public String getIcon() { + return CLASS_ICON; + } + + public String getLeftText() { + StringBuilder sb = new StringBuilder(); + if (isDeprecated) { + sb.append(""); // NOI18N + } + sb.append(""); // NOI18N + sb.append(element.getName()); + sb.append(""); // NOI18N + if (isDeprecated) { + sb.append(""); // NOI18N + } + + return sb.toString(); + } + + public String getRightText() { + StringBuilder sb = new StringBuilder(); + + final String in = element.getIn(); + if (in != null && in.length() > 0) { + sb.append(in); + return sb.toString(); + } else if (element instanceof PhpElement) { + PhpElement ie = (PhpElement) element; + if (isPlatform) { + return "PHP Platform"; // NOI18N + } + + String filename = ie.getFilenameUrl(); + int index = filename.lastIndexOf('/'); + if (index != -1) { + filename = filename.substring(index + 1); + } + + sb.append(filename); + return sb.toString(); + } + + return null; + } + + @Override + public CompletionTask createDocumentationTask() { + return null; + } + + @Override + public CompletionTask createToolTipTask() { + return null; + } + + @Override + public boolean instantSubstitution(JTextComponent component) { + return false; + } + + @Override + public int getSortPriority() { + return 0; + } + + @Override + public CharSequence getSortText() { + return getName(); + } + + @Override + public CharSequence getInsertPrefix() { + return element.getName(); + } + + public String getName() { + return element.getName(); + } + + public static class Builtin extends ExceptionCompletionItem { + + private final String element; + + public Builtin(String element) { + super(null); + this.element = element; + } + + @Override + public String getIcon() { + return PLATFORM_ICON; + } + + @Override + public String getRightText() { + return ""; + } + + @Override + public String getLeftText() { + return this.element; + } + + @Override + public String getName() { + return this.element; + } + + @Override + public int getSortPriority() { + return -1; + } + + @Override + public CharSequence getInsertPrefix() { + return element; + } + } + +} diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionCompletionProvider.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionCompletionProvider.java new file mode 100644 index 000000000000..e11216bc3510 --- /dev/null +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionCompletionProvider.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.php.dbgp.ui.completion; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import org.netbeans.api.editor.mimelookup.MimeRegistration; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ui.OpenProjects; +import org.netbeans.modules.csl.spi.support.CancelSupport; +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind; +import org.netbeans.modules.php.api.phpmodule.PhpModule; +import org.netbeans.modules.php.editor.api.ElementQuery; +import org.netbeans.modules.php.editor.api.ElementQueryFactory; +import org.netbeans.modules.php.editor.api.NameKind; +import org.netbeans.modules.php.editor.api.QuerySupportFactory; +import org.netbeans.modules.php.editor.api.elements.ClassElement; +import org.netbeans.spi.editor.completion.CompletionProvider; +import static org.netbeans.spi.editor.completion.CompletionProvider.COMPLETION_QUERY_TYPE; +import org.netbeans.spi.editor.completion.CompletionResultSet; +import org.netbeans.spi.editor.completion.CompletionTask; +import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery; +import org.netbeans.spi.editor.completion.support.AsyncCompletionTask; +import org.openide.filesystems.FileObject; + +@MimeRegistration(mimeType = ExceptionClassNbDebugEditorKit.MIME_TYPE, service = CompletionProvider.class) +public class ExceptionCompletionProvider implements CompletionProvider { + + private static final Logger LOG = Logger.getLogger(ExceptionCompletionProvider.class.getName()); + + private final Set builtinErrors = new HashSet<>(Arrays.asList("Deprecated","Notice", "Warning")); // NOI18N + + @Override + public CompletionTask createTask(int queryType, JTextComponent component) { + if (queryType != CompletionProvider.COMPLETION_QUERY_TYPE) { + return null; + } + + return new AsyncCompletionTask(new AsyncCompletionQuery() { + @Override + protected void query(CompletionResultSet resultSet, Document doc, int caretOffset) { + if (caretOffset < 0) { + caretOffset = 0; + } + String text; + try { + text = doc.getText(0, caretOffset); + } catch (BadLocationException ex) { + LOG.log(Level.WARNING, "Invalid offset: {0}", ex.offsetRequested()); // NOI18N + text = ""; // NOI18N + } + + for (String builtinError: builtinErrors) { + resultSet.addItem(new ExceptionCompletionItem.Builtin(builtinError)); + } + +//https://stackoverflow.com/questions/16090681/retrieving-location-of-currently-opened-file-or-project-in-netbeans + + Set items = new HashSet<>(); + + for (Project project : OpenProjects.getDefault().getOpenProjects()) { + PhpModule module = PhpModule.Factory.lookupPhpModule(project); + if (module != null) { + FileObject source = module.getProjectDirectory(); + + ElementQuery.Index index = ElementQueryFactory.createIndexQuery(QuerySupportFactory.get(source)); + + NameKind nameQuery = NameKind.create(text, Kind.CASE_INSENSITIVE_PREFIX); + Set classes = index.getClasses(nameQuery); + for (ClassElement classElement : classes) { + if (CancelSupport.getDefault().isCancelled()) { + return; + } + if (isException(classElement)) { + items.add(classElement); + continue; + } + if (classElement.getSuperClassName() != null) { + Set inheritedClasses = index.getInheritedClasses(classElement); + for (ClassElement inheritedClass : inheritedClasses) { + if (CancelSupport.getDefault().isCancelled()) { + return; + } + if (isException(inheritedClass)) { + items.add(classElement); + break; + } + } + } + } + } else { + LOG.log(Level.WARNING, "No php module found for the project {0}", project); // NOI18N + } + } + + for (ClassElement item: items) { + resultSet.addItem(new ExceptionCompletionItem(item)); + } + + resultSet.finish(); + } + }, component); + } + + private boolean isException(ClassElement element) { + return element.getFullyQualifiedName().toString().equals("\\Exception"); // NOI18N + } + + @Override + public int getAutoQueryTypes(JTextComponent component, String typedText) { + return COMPLETION_QUERY_TYPE; + } + +}