This is an automated email from the ASF dual-hosted git repository.

junichi11 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 5f1c9da3c5 Added support for exception breakpoints. #5434 
Breakpoint_set and breakpoint_remove commands are used instead of 
breakpoint_update to change breakpoint state during debugging. Fixed a bug 
where the previous breakpoint was displayed as the current breakpoint if the 
current breakpoint was not found.
     new d507933d27 Merge pull request #6366 from troizet/exception_breakpoint
5f1c9da3c5 is described below

commit 5f1c9da3c5f11cde0cbe11d251dfbd892b6ba0e1
Author: Alexey Borokhvostov <troi...@gmail.com>
AuthorDate: Sun Apr 9 19:50:03 2023 +0700

    Added support for exception breakpoints. #5434
    Breakpoint_set and breakpoint_remove commands are used instead of 
breakpoint_update to change breakpoint state during debugging.
    Fixed a bug where the previous breakpoint was displayed as the current 
breakpoint if the current breakpoint was not found.
---
 php/php.dbgp/licenseinfo.xml                       |   2 +
 php/php.dbgp/nbproject/project.xml                 |  17 ++
 .../org.netbeans.spi.debugger.ui.BreakpointType    |   1 +
 .../php/dbgp/breakpoints/BreakpointModel.java      |  28 ++-
 .../dbgp/breakpoints/BreakpointRuntimeSetter.java  |   7 +-
 .../php/dbgp/breakpoints/BreakpointsReader.java    |  35 +++-
 .../modules/php/dbgp/breakpoints/Bundle.properties |   1 +
 .../breakpoints/DbgpExceptionBreakpointType.java   |  66 +++++++
 .../php/dbgp/breakpoints/ExceptionBreakpoint.java  |  44 +++++
 .../modules/php/dbgp/breakpoints/Utils.java        |   3 +
 .../php/dbgp/packets/BrkpntCommandBuilder.java     |   8 +
 .../modules/php/dbgp/packets/BrkpntSetCommand.java |   2 +-
 .../modules/php/dbgp/packets/InitMessage.java      |   6 +-
 .../netbeans/modules/php/dbgp/resources/class.png  | Bin 0 -> 785 bytes
 .../netbeans/modules/php/dbgp/resources/layer.xml  |   6 +
 .../modules/php/dbgp/resources/php16Key.png        | Bin 0 -> 589 bytes
 .../netbeans/modules/php/dbgp/ui/Bundle.properties |   3 +
 .../php/dbgp/ui/DbgpExceptionBreakpointPanel.form  | 101 ++++++++++
 .../php/dbgp/ui/DbgpExceptionBreakpointPanel.java  | 143 ++++++++++++++
 .../completion/ExceptionClassNbDebugEditorKit.java |  31 +++
 .../ui/completion/ExceptionCompletionItem.java     | 210 +++++++++++++++++++++
 .../ui/completion/ExceptionCompletionProvider.java | 136 +++++++++++++
 22 files changed, 832 insertions(+), 18 deletions(-)

diff --git a/php/php.dbgp/licenseinfo.xml b/php/php.dbgp/licenseinfo.xml
index bc74327931..e2e85decee 100644
--- a/php/php.dbgp/licenseinfo.xml
+++ b/php/php.dbgp/licenseinfo.xml
@@ -21,7 +21,9 @@
 -->
 <licenseinfo>
     <fileset>
+        <file>src/org/netbeans/modules/php/dbgp/resources/class.png</file>
         
<file>src/org/netbeans/modules/php/dbgp/resources/notice-glyph.gif</file>
+        <file>src/org/netbeans/modules/php/dbgp/resources/php16Key.png</file>
         <file>src/org/netbeans/modules/php/dbgp/resources/undefined.gif</file>
         <license ref="Apache-2.0-ASF" />
         <comment type="COMMENT_UNSUPPORTED" />
diff --git a/php/php.dbgp/nbproject/project.xml 
b/php/php.dbgp/nbproject/project.xml
index 52a8070579..f5f5b12b93 100644
--- a/php/php.dbgp/nbproject/project.xml
+++ b/php/php.dbgp/nbproject/project.xml
@@ -87,6 +87,15 @@
                         <specification-version>1.58</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.modules.editor.completion</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.67</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     
<code-name-base>org.netbeans.modules.editor.document</code-name-base>
                     <build-prerequisite/>
@@ -149,6 +158,14 @@
                         <specification-version>9.0</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.modules.parsing.indexing</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.31</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     
<code-name-base>org.netbeans.modules.php.api.executable</code-name-base>
                     <build-prerequisite/>
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 11de7f04d4..f5d02c2d83 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 339522e91a..aea90c8684 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<DebugSession, AbstractBreakpoint> myCurrentBreakpoints;
 
@@ -74,6 +75,12 @@ public class BreakpointModel extends ViewModelSupport 
implements NodeModel {
             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 class BreakpointModel extends ViewModelSupport 
implements NodeModel {
 
     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 class BreakpointModel extends ViewModelSupport 
implements NodeModel {
         }
 
     }
-
 }
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 8871164ef3..3c38c12bc4 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 class BreakpointRuntimeSetter extends 
DebuggerManagerAdapter {
             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 4962e0bb1c..890276a1db 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 @@ import org.openide.text.Line;
  */
 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 class BreakpointsReader implements Properties.Reader {
                 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 class BreakpointsReader implements Properties.Reader 
{
                 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 class BreakpointsReader implements Properties.Reader {
             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 class BreakpointsReader implements Properties.Reader 
{
             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 21466d8382..17c84b653e 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 0000000000..77bdcfffa8
--- /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 0000000000..0c421ef92e
--- /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 bc291dcfdb..a247241a34 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 final class Utils {
             } 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 07a2f28dfb..5e8e51c90b 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 final class BrkpntCommandBuilder {
         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 1bdbced42a..b0edacd7bb 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 c68ddde083..426de51421 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 @@ public class InitMessage extends DbgpMessage {
         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 0000000000..220e6f385e
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 0e1261e3b7..7b2f67179c 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 @@
                     </file>
                 </folder>
             </folder>
+            <folder name="x-php-nbdebug-class-exception">
+                <file name="EditorKit.instance">
+                    <attr name="instanceClass"
+                          
stringvalue="org.netbeans.modules.php.dbgp.ui.completion.ExceptionClassNbDebugEditorKit"/>
+                </file>
+            </folder>
        </folder>
         <folder name="AnnotationTypes">
             <file name="PHPError.xml" url="PHPError.xml"/>
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 0000000000..4cf41724a8
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 f500731c88..5552c62af6 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 0000000000..759e628403
--- /dev/null
+++ 
b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpExceptionBreakpointPanel.form
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+
+    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.
+
+-->
+
+<Form version="1.4" maxVersion="1.5" 
type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <Properties>
+    <Property name="border" type="javax.swing.border.Border" 
editor="org.netbeans.modules.form.editors2.BorderEditor">
+      <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+        <TitledBorder title="Settings">
+          <ResourceString PropertyName="titleX" 
bundle="org/netbeans/modules/php/dbgp/ui/Bundle.properties" key="LBL_Settings" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+        </TitledBorder>
+      </Border>
+    </Property>
+  </Properties>
+  <AccessibilityProperties>
+    <Property name="AccessibleContext.accessibleName" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+      <ResourceString 
bundle="org/netbeans/modules/php/dbgp/ui/Bundle.properties" 
key="A11_SettingsName" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+    </Property>
+  </AccessibilityProperties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" 
value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" 
type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" 
value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" 
type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" 
value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" 
value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" 
type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" 
value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" 
value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="classNameEditorPanel" pref="361" max="32767" 
attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Component id="classNameEditorPanel" min="-2" pref="36" max="-2" 
attributes="0"/>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JPanel" name="classNameEditorPanel">
+      <AccessibilityProperties>
+        <Property name="AccessibleContext.accessibleName" 
type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString 
bundle="org/netbeans/modules/php/dbgp/ui/Bundle.properties" 
key="A11_SettingsName" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+        </Property>
+      </AccessibilityProperties>
+
+      <Layout 
class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="exceptionLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString 
bundle="org/netbeans/modules/php/dbgp/ui/Bundle.properties" 
key="LBL_ExceptionName" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+            </Property>
+            <Property name="verticalAlignment" type="int" value="1"/>
+          </Properties>
+          <AccessibilityProperties>
+            <Property name="AccessibleContext.accessibleName" 
type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString 
bundle="org/netbeans/modules/php/dbgp/ui/Bundle.properties" 
key="DbgpExceptionBreakpointPanel.exceptionLabel.AccessibleContext.accessibleName"
 replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+            </Property>
+            <Property name="AccessibleContext.accessibleDescription" 
type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString 
bundle="org/netbeans/modules/php/dbgp/ui/Bundle.properties" 
key="DbgpExceptionBreakpointPanel.exceptionLabel.AccessibleContext.accessibleDescription"
 replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+            </Property>
+          </AccessibilityProperties>
+          <Constraints>
+            <Constraint 
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" 
value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" 
gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" 
insetsBottom="3" insetsRight="3" anchor="21" weightX="0.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>
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 0000000000..a6ccf88198
--- /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<JScrollPane, JEditorPane> 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<JScrollPane, JEditorPane> 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.<JScrollPane, JEditorPane>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.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated 
Code">//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
+    }// </editor-fold>//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 0000000000..d9a8f16b58
--- /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 0000000000..fb4bfa39f9
--- /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("<s>"); // NOI18N
+        }
+        sb.append("<font color=\"#560000\">"); // NOI18N
+        sb.append(element.getName());
+        sb.append("</font>"); // NOI18N
+        if (isDeprecated) {
+            sb.append("</s>"); // 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 0000000000..e11216bc35
--- /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<String> 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<ClassElement> 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<ClassElement> 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<ClassElement> 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;
+    }
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to