You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by en...@apache.org on 2022/05/27 09:13:17 UTC

[netbeans] branch master updated: Groovy debugger in a separate module, depends on Groovy parser to retrieve names of Groovy classes.

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

entl 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 70b588e4c8 Groovy debugger in a separate module, depends on Groovy parser to retrieve names of Groovy classes.
70b588e4c8 is described below

commit 70b588e4c8245d5075821405b9012d35363bbf71
Author: Martin Entlicher <ma...@oracle.com>
AuthorDate: Thu May 26 00:52:13 2022 +0200

    Groovy debugger in a separate module, depends on Groovy parser to retrieve names of Groovy classes.
---
 groovy/groovy.debug/build.xml                      |  25 ++++
 groovy/groovy.debug/manifest.mf                    |   6 +
 .../nbproject/project.properties}                  |   6 +-
 groovy/groovy.debug/nbproject/project.xml          | 154 ++++++++++++++++++++
 .../netbeans/modules/groovy}/debug/Context.java    |   6 +-
 .../debug/GroovyBreakpointActionsProvider.java     |   9 +-
 .../debug/GroovyBreakpointAnnotationListener.java  |  27 ++--
 .../groovy/debug/GroovyBreakpointStratifier.java   | 157 +++++++++++++++++++++
 .../modules/groovy}/debug/GroovySmartStepping.java |   2 +-
 .../GroovyToggleBreakpointActionProvider.java      |  43 +++---
 .../groovy/debug/resources/Bundle.properties}      |   5 +-
 .../modules/groovy/debug}/resources/layer.xml      |  17 +--
 groovy/groovy.editor/nbproject/project.xml         |   1 +
 groovy/groovy.kit/nbproject/project.xml            |   7 +
 groovy/groovy.support/nbproject/project.xml        |  18 ---
 ...etbeans.spi.viewmodel.NodeActionsProviderFilter |  18 ---
 .../support/debug/GroovyLineBreakpointFactory.java | 121 ----------------
 .../modules/groovy/support/resources/layer.xml     |  12 +-
 groovy/libs.groovy/nbproject/project.xml           |   1 +
 java/api.debugger.jpda/apichanges.xml              |  14 ++
 java/api.debugger.jpda/manifest.mf                 |   2 +-
 .../netbeans/api/debugger/jpda/LineBreakpoint.java |   8 ++
 .../spi/debugger/jpda/BreakpointStratifier.java    |  52 +++++++
 .../jpda/breakpoints/BreakpointsReader.java        |   7 +-
 java/java.lsp.server/nbproject/project.xml         |   2 +-
 .../breakpoints/GroovyBreakpointFactory.java       | 110 ---------------
 .../server/debugging/breakpoints/NbBreakpoint.java |   8 +-
 nbbuild/cluster.properties                         |   1 +
 28 files changed, 488 insertions(+), 351 deletions(-)

diff --git a/groovy/groovy.debug/build.xml b/groovy/groovy.debug/build.xml
new file mode 100644
index 0000000000..6f5b102f70
--- /dev/null
+++ b/groovy/groovy.debug/build.xml
@@ -0,0 +1,25 @@
+<?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.
+
+-->
+<project basedir="." default="build" name="groovy/groovy.debug">
+    <description>Builds, tests, and runs the project org.netbeans.modules.groovy.debug</description>
+    <import file="../../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/groovy/groovy.debug/manifest.mf b/groovy/groovy.debug/manifest.mf
new file mode 100644
index 0000000000..e04d36c7fe
--- /dev/null
+++ b/groovy/groovy.debug/manifest.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: false
+OpenIDE-Module: org.netbeans.modules.groovy.debug/1
+OpenIDE-Module-Layer: org/netbeans/modules/groovy/debug/resources/layer.xml
+OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/groovy/debug/resources/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
diff --git a/groovy/groovy.support/src/META-INF.debugger/org.netbeans.api.debugger.LazyDebuggerManagerListener b/groovy/groovy.debug/nbproject/project.properties
similarity index 86%
rename from groovy/groovy.support/src/META-INF.debugger/org.netbeans.api.debugger.LazyDebuggerManagerListener
rename to groovy/groovy.debug/nbproject/project.properties
index 358ce86cc0..c0d9833995 100644
--- a/groovy/groovy.support/src/META-INF.debugger/org.netbeans.api.debugger.LazyDebuggerManagerListener
+++ b/groovy/groovy.debug/nbproject/project.properties
@@ -14,5 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
-org.netbeans.modules.groovy.support.debug.GroovyBreakpointAnnotationListener
+javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.8
+cp.extra=${tools.jar}
+nbm.homepage=http://wiki.netbeans.org/groovy
diff --git a/groovy/groovy.debug/nbproject/project.xml b/groovy/groovy.debug/nbproject/project.xml
new file mode 100644
index 0000000000..60ed07c1a2
--- /dev/null
+++ b/groovy/groovy.debug/nbproject/project.xml
@@ -0,0 +1,154 @@
+<?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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.netbeans.modules.groovy.debug</code-name-base>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.debugger</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.14</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.debugger.jpda</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>2</release-version>
+                        <specification-version>3.27</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.java.classpath</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.csl.types</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>3</release-version>
+                        <specification-version>4.24</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.groovy.editor</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>3</release-version>
+                        <specification-version>1.85</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.libs.groovy</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>2.12</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.spi.debugger.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>2.13</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.spi.viewmodel</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>2</release-version>
+                        <specification-version>1.15</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+	    <public-packages/>
+        </data>
+    </configuration>
+</project>
diff --git a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/Context.java b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/Context.java
similarity index 96%
rename from groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/Context.java
rename to groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/Context.java
index f7c1535103..e1e80dd2e5 100644
--- a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/Context.java
+++ b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/Context.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.netbeans.modules.groovy.support.debug;
+package org.netbeans.modules.groovy.debug;
 
 import java.beans.PropertyChangeListener;
 import java.io.File;
@@ -40,9 +40,9 @@ public class Context {
 
     private static EditorContext getContext() {
         if (editorContext == null) {
-            List l = DebuggerManager.getDebuggerManager().lookup(null, EditorContext.class);
+            List<? extends EditorContext> l = DebuggerManager.getDebuggerManager().lookup(null, EditorContext.class);
             if (!l.isEmpty()) {
-                editorContext = (EditorContext) l.get(0);
+                editorContext = l.get(0);
             }
         }
         return editorContext;
diff --git a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyBreakpointActionsProvider.java b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyBreakpointActionsProvider.java
similarity index 92%
rename from groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyBreakpointActionsProvider.java
rename to groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyBreakpointActionsProvider.java
index ab3f989143..6e17074358 100644
--- a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyBreakpointActionsProvider.java
+++ b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyBreakpointActionsProvider.java
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.netbeans.modules.groovy.support.debug;
+package org.netbeans.modules.groovy.debug;
 
 import javax.swing.Action;
 import org.netbeans.api.debugger.jpda.LineBreakpoint;
-import static org.netbeans.modules.groovy.support.debug.Bundle.*;
+import org.netbeans.spi.debugger.DebuggerServiceRegistration;
 import org.netbeans.spi.viewmodel.ModelListener;
 import org.netbeans.spi.viewmodel.Models;
 import org.netbeans.spi.viewmodel.NodeActionsProvider;
@@ -32,11 +32,12 @@ import org.openide.util.NbBundle.Messages;
  * @author Martin Grebac
  * @author Martin Adamek
  */
+@DebuggerServiceRegistration(path="BreakpointsView", types=NodeActionsProviderFilter.class)
 public class GroovyBreakpointActionsProvider implements NodeActionsProviderFilter {
 
     @Messages("LBL_Action_Go_To_Source=Go to Source")
     private static final Action GO_TO_SOURCE_ACTION = Models.createAction(
-            LBL_Action_Go_To_Source(),
+            Bundle.LBL_Action_Go_To_Source(),
             new Models.ActionPerformer() {
                 @Override
                 public boolean isEnabled(Object node) {
@@ -52,7 +53,7 @@ public class GroovyBreakpointActionsProvider implements NodeActionsProviderFilte
     
     @Messages("LBL_Action_Customize=Customize")
     private static final Action CUSTOMIZE_ACTION = Models.createAction(
-            LBL_Action_Customize(),
+            Bundle.LBL_Action_Customize(),
             new Models.ActionPerformer() {
                 @Override
                 public boolean isEnabled(Object node) {
diff --git a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyBreakpointAnnotationListener.java b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyBreakpointAnnotationListener.java
similarity index 93%
rename from groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyBreakpointAnnotationListener.java
rename to groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyBreakpointAnnotationListener.java
index 2d83d692ba..d6c70601dd 100644
--- a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyBreakpointAnnotationListener.java
+++ b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyBreakpointAnnotationListener.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.netbeans.modules.groovy.support.debug;
+package org.netbeans.modules.groovy.debug;
 
 import java.beans.PropertyChangeEvent;
 import java.util.HashMap;
@@ -25,8 +25,10 @@ import org.netbeans.api.debugger.Breakpoint;
 import org.netbeans.api.debugger.DebuggerEngine;
 import org.netbeans.api.debugger.DebuggerManager;
 import org.netbeans.api.debugger.DebuggerManagerAdapter;
+import org.netbeans.api.debugger.LazyDebuggerManagerListener;
 import org.netbeans.api.debugger.jpda.JPDADebugger;
 import org.netbeans.api.debugger.jpda.LineBreakpoint;
+import org.netbeans.spi.debugger.DebuggerServiceRegistration;
 
 /**
  * Listens on {@org.netbeans.api.debugger.DebuggerManager} on
@@ -37,16 +39,17 @@ import org.netbeans.api.debugger.jpda.LineBreakpoint;
  * @author Martin Grebac
  * @author Martin Adamek
  */
+@DebuggerServiceRegistration(types=LazyDebuggerManagerListener.class)
 public class GroovyBreakpointAnnotationListener extends DebuggerManagerAdapter {
-    
+
     private HashMap<LineBreakpoint, Object> breakpointToAnnotation = new HashMap<>();
     private boolean listen = true;
-    
+
     @Override
     public String[] getProperties () {
         return new String[] {DebuggerManager.PROP_BREAKPOINTS};
     }
-    
+
     @Override
     public void propertyChange (PropertyChangeEvent e) {
         String propertyName = e.getPropertyName ();
@@ -80,7 +83,7 @@ public class GroovyBreakpointAnnotationListener extends DebuggerManagerAdapter {
             removeAnnotation ((LineBreakpoint) b);
         }
     }
-    
+
     private void annotate (LineBreakpoint b) {
         // remove old annotation
         Object annotation = breakpointToAnnotation.get (b);
@@ -90,31 +93,31 @@ public class GroovyBreakpointAnnotationListener extends DebuggerManagerAdapter {
         if (b.isHidden ()) {
             return;
         }
-        
+
         // add new one
         annotation = Context.annotate (b);
         if (annotation == null) {
             return;
         }
-        
+
         breakpointToAnnotation.put (b, annotation);
-        
+
         DebuggerEngine de = DebuggerManager.getDebuggerManager().getCurrentEngine ();
         Object timeStamp = null;
         if (de != null) {
             timeStamp = de.lookupFirst (null, JPDADebugger.class);
         }
-        update (b, timeStamp);        
+        update (b, timeStamp);
     }
 
     public void updateGroovyLineBreakpoints () {
-        Iterator<LineBreakpoint> it = breakpointToAnnotation.keySet ().iterator (); 
+        Iterator<LineBreakpoint> it = breakpointToAnnotation.keySet ().iterator ();
         while (it.hasNext ()) {
             LineBreakpoint lb = it.next();
             update (lb, null);
         }
     }
-    
+
     private void update (LineBreakpoint b, Object timeStamp) {
         Object annotation = breakpointToAnnotation.get (b);
         if (annotation == null) {
@@ -125,7 +128,7 @@ public class GroovyBreakpointAnnotationListener extends DebuggerManagerAdapter {
         b.setLineNumber (ln);
         listen = true;
     }
-    
+
     private void removeAnnotation(LineBreakpoint b) {
         Object annotation = breakpointToAnnotation.remove (b);
         if (annotation != null) {
diff --git a/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyBreakpointStratifier.java b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyBreakpointStratifier.java
new file mode 100644
index 0000000000..f73b0a8110
--- /dev/null
+++ b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyBreakpointStratifier.java
@@ -0,0 +1,157 @@
+/*
+ * 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.groovy.debug;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.codehaus.groovy.ast.ASTNode;
+import org.netbeans.api.debugger.jpda.JPDABreakpoint;
+import org.netbeans.api.debugger.jpda.LineBreakpoint;
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.modules.groovy.editor.api.ASTUtils;
+import org.netbeans.modules.groovy.editor.api.AstPath;
+import org.netbeans.modules.groovy.editor.api.parser.GroovyLanguage;
+import org.netbeans.modules.groovy.editor.api.parser.GroovyParserResult;
+import org.netbeans.modules.parsing.api.ParserManager;
+import org.netbeans.modules.parsing.api.ResultIterator;
+import org.netbeans.modules.parsing.api.Source;
+import org.netbeans.modules.parsing.api.UserTask;
+import org.netbeans.modules.parsing.spi.ParseException;
+import org.netbeans.spi.debugger.jpda.BreakpointStratifier;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.filesystems.URLMapper;
+import org.openide.util.NbBundle.Messages;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ * Modifies breakpoints to adapt to the Groovy stratum.
+ *
+ * @author Martin Janicek
+ */
+@ServiceProvider(service = BreakpointStratifier.class)
+public final class GroovyBreakpointStratifier implements BreakpointStratifier {
+
+    private static final Logger LOGGER = Logger.getLogger(GroovyBreakpointStratifier.class.getName());
+
+    public GroovyBreakpointStratifier() {
+    }
+
+    /**
+     * Creates a new breakpoint for the given parameters.
+     *
+     * @param url a url
+     * @param lineNumber a line number
+     * @return a new breakpoint for given parameters
+     */
+    @Override
+    @Messages("CTL_Default_Print_Text=Breakpoint reached at line {lineNumber} in {groovyName} by thread {threadName}.")
+    public void stratify(JPDABreakpoint breakpoint) {
+        if (breakpoint instanceof LineBreakpoint) {
+            LineBreakpoint lb = (LineBreakpoint) breakpoint;
+            String url = lb.getURL();
+            FileObject fo = getFileObjectFromUrl(url);
+            if (fo != null && GroovyLanguage.GROOVY_MIME_TYPE.equals(fo.getMIMEType())) {
+                int lineNumber = lb.getLineNumber();
+                String groovyName = fo.getNameExt();
+                String pt = Bundle.CTL_Default_Print_Text();
+                String printText = pt.replace("{groovyName}", (groovyName != null) ? groovyName : "?"); // NOI18N
+                String groovyPath = getGroovyPath(url, fo);
+
+                lb.setStratum("Groovy"); // NOI18N
+                lb.setSourceName(groovyName);
+                lb.setSourcePath(groovyPath);
+                lb.setPreferredClassName(findGroovyClassName(groovyPath, fo, lineNumber));
+                lb.setPrintText(printText);
+            }
+        }
+    }
+
+    private static FileObject getFileObjectFromUrl(String url) {
+
+        FileObject fo = null;
+
+        try {
+            fo = URLMapper.findFileObject(new URL(url));
+        } catch (MalformedURLException e) {
+            //noop
+        }
+        return fo;
+    }
+
+    private static String findGroovyClassName(String relativePath, FileObject fo, int lineNumber) {
+        Source source = Source.create(fo);
+        String[] className = new String[] { null };
+        try {
+            ParserManager.parse(Collections.singleton(source), new UserTask() {
+                public @Override void run(ResultIterator resultIterator) throws Exception {
+                    GroovyParserResult result = ASTUtils.getParseResult(resultIterator.getParserResult());
+                    ASTNode root = ASTUtils.getRoot(result);
+                    AstPath path = new AstPath(root, lineNumber, 0);
+                    className[0] = ASTUtils.getFqnName(path);
+                }
+            });
+        } catch (ParseException ex) {
+        }
+        if (className[0] != null) {
+            return className[0];
+        } else {
+            return getClassFilter(relativePath);
+        }
+    }
+
+    private static String getClassFilter(String relativePath) {
+        if (relativePath == null) {
+            return "";
+        }
+
+        int dot = relativePath.lastIndexOf('.');
+        if (dot > 0) {
+            relativePath = relativePath.substring(0, dot);
+        }
+        return relativePath.replace('/', '.') + "*";
+    }
+
+    private static String getGroovyPath(String url, FileObject fo) {
+        if (fo != null) {
+            String relativePath;
+            ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
+            if (cp != null) {
+                FileObject root = cp.findOwnerRoot(fo);
+                if (root != null) {
+                    relativePath = FileUtil.getRelativePath(root, fo);
+                } else {
+                    // Suppose the current folder
+                    relativePath = fo.getNameExt();
+                }
+            } else {
+                LOGGER.log(Level.FINE, "No classpath for {0}", url);
+                // Suppose the current folder
+                relativePath = fo.getNameExt();
+                return relativePath;
+            }
+            return relativePath;
+        }
+        return url;
+    }
+}
diff --git a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovySmartStepping.java b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovySmartStepping.java
similarity index 98%
rename from groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovySmartStepping.java
rename to groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovySmartStepping.java
index 946a74f786..9f37851970 100644
--- a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovySmartStepping.java
+++ b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovySmartStepping.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.netbeans.modules.groovy.support.debug;
+package org.netbeans.modules.groovy.debug;
 
 import java.util.Arrays;
 import java.util.Collections;
diff --git a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyToggleBreakpointActionProvider.java b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyToggleBreakpointActionProvider.java
similarity index 87%
rename from groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyToggleBreakpointActionProvider.java
rename to groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyToggleBreakpointActionProvider.java
index aedc3a745b..6acdf3e43e 100644
--- a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyToggleBreakpointActionProvider.java
+++ b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/GroovyToggleBreakpointActionProvider.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.netbeans.modules.groovy.support.debug;
+package org.netbeans.modules.groovy.debug;
 
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
@@ -28,70 +28,71 @@ import org.netbeans.api.debugger.Breakpoint;
 import org.netbeans.api.debugger.DebuggerManager;
 import org.netbeans.api.debugger.jpda.JPDADebugger;
 import org.netbeans.api.debugger.jpda.LineBreakpoint;
+import org.netbeans.modules.groovy.editor.api.parser.GroovyLanguage;
 import org.netbeans.spi.debugger.ActionsProvider.Registration;
 import org.netbeans.spi.debugger.ActionsProviderSupport;
 import org.netbeans.spi.debugger.ContextProvider;
 import org.openide.filesystems.FileObject;
 
-/** 
+/**
  * Toggle Groovy Breakpoint action provider.
  *
  * @author Martin Grebac
  * @author Martin Adamek
  */
-@Registration(actions={"toggleBreakpoint"}, activateForMIMETypes={"text/x-groovy"})
+@Registration(actions={"toggleBreakpoint"}, activateForMIMETypes={GroovyLanguage.GROOVY_MIME_TYPE})
 public class GroovyToggleBreakpointActionProvider extends ActionsProviderSupport implements PropertyChangeListener {
-    
+
     private JPDADebugger debugger;
-    
+
     public GroovyToggleBreakpointActionProvider () {
         Context.addPropertyChangeListener (this);
         setEnabled (ActionsManager.ACTION_TOGGLE_BREAKPOINT, false);
     }
-    
+
     public GroovyToggleBreakpointActionProvider (ContextProvider contextProvider) {
         debugger = contextProvider.lookupFirst(null, JPDADebugger.class);
         debugger.addPropertyChangeListener (JPDADebugger.PROP_STATE, this);
         Context.addPropertyChangeListener (this);
         setEnabled (ActionsManager.ACTION_TOGGLE_BREAKPOINT, false);
     }
-    
+
     private void destroy () {
         debugger.removePropertyChangeListener (JPDADebugger.PROP_STATE, this);
         Context.removePropertyChangeListener (this);
     }
-    
+
     @Override
     public void propertyChange (PropertyChangeEvent evt) {
         FileObject fo = Context.getCurrentFile();
-        boolean isGroovyFile = fo != null && 
-                "text/x-groovy".equals(fo.getMIMEType()); // NOI18N [TODO]
-        
+        boolean isGroovyFile = fo != null &&
+                GroovyLanguage.GROOVY_MIME_TYPE.equals(fo.getMIMEType());
+
         setEnabled(ActionsManager.ACTION_TOGGLE_BREAKPOINT, isGroovyFile);
-        if ( debugger != null && 
-             debugger.getState () == JPDADebugger.STATE_DISCONNECTED
-        ) 
+        if (debugger != null && debugger.getState () == JPDADebugger.STATE_DISCONNECTED) {
             destroy ();
+        }
     }
-    
+
     @Override
     public Set getActions () {
         return Collections.singleton (ActionsManager.ACTION_TOGGLE_BREAKPOINT);
     }
-    
+
     @Override
     public void doAction (Object action) {
         DebuggerManager debugManager = DebuggerManager.getDebuggerManager ();
-        
+
         // 1) get source name & line number
         int lineNumber = Context.getCurrentLineNumber ();
         String url = Context.getCurrentURL ();
-        if (url == null) return;
-                
+        if (url == null) {
+            return;
+        }
+
         // 2) find and remove existing line breakpoint
         for (Breakpoint breakpoint : debugManager.getBreakpoints()) {
             if (breakpoint instanceof LineBreakpoint) {
-                
                 LineBreakpoint lineBreakpoint = ((LineBreakpoint) breakpoint);
                 if (lineNumber == lineBreakpoint.getLineNumber() && url.equals(lineBreakpoint.getURL())) {
                     debugManager.removeBreakpoint(breakpoint);
@@ -101,6 +102,6 @@ public class GroovyToggleBreakpointActionProvider extends ActionsProviderSupport
         }
 
         // 3) Add new groovy line breakpoint
-        debugManager.addBreakpoint(GroovyLineBreakpointFactory.create(url, lineNumber));
+        debugManager.addBreakpoint(LineBreakpoint.create(url, lineNumber));
     }
 }
diff --git a/groovy/groovy.support/src/META-INF.debugger/org.netbeans.modules.groovy.support.debug.GroovyBreakpointAnnotationListener b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/resources/Bundle.properties
similarity index 79%
rename from groovy/groovy.support/src/META-INF.debugger/org.netbeans.modules.groovy.support.debug.GroovyBreakpointAnnotationListener
rename to groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/resources/Bundle.properties
index 358ce86cc0..b90017b6e6 100644
--- a/groovy/groovy.support/src/META-INF.debugger/org.netbeans.modules.groovy.support.debug.GroovyBreakpointAnnotationListener
+++ b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/resources/Bundle.properties
@@ -15,4 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-org.netbeans.modules.groovy.support.debug.GroovyBreakpointAnnotationListener
+OpenIDE-Module-Display-Category=Groovy
+OpenIDE-Module-Long-Description=This module implements Groovy debugging
+OpenIDE-Module-Name=Groovy Debugger
+OpenIDE-Module-Short-Description=Debugger of Groovy scripts
diff --git a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/resources/layer.xml b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/resources/layer.xml
similarity index 64%
copy from groovy/groovy.support/src/org/netbeans/modules/groovy/support/resources/layer.xml
copy to groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/resources/layer.xml
index d5cdc61f7e..39a8af4b9c 100644
--- a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/resources/layer.xml
+++ b/groovy/groovy.debug/src/org/netbeans/modules/groovy/debug/resources/layer.xml
@@ -21,13 +21,6 @@
 -->
 <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
 <filesystem>
-    <folder name="Templates">
-        <folder name="Groovy">
-            <attr name="displayName" bundlevalue="org.netbeans.modules.groovy.support.Bundle#Templates/Groovy"/>
-            <attr name="position" intvalue="1350"/>
-            <attr name="templateWizardURL" urlvalue="nbresloc:/org/netbeans/modules/groovy/support/resources/Groovy.html"/>
-        </folder>
-    </folder>
     <folder name="Editors">
         <folder name="text">
             <folder name="x-groovy">
@@ -36,14 +29,6 @@
                         <attr name="originalFile" stringvalue="Actions/Debug/org-netbeans-modules-debugger-ui-actions-ToggleBreakpointAction.instance"/>
                         <attr name="position" intvalue="1750"/>
                     </file>
-                    <file name="org-netbeans-modules-gsf-testrunner-TestMethodRunnerAction.shadow">
-                        <attr name="originalFile" stringvalue="Actions/CommonTestRunner/org-netbeans-modules-gsf-testrunner-TestMethodRunnerAction.instance"/>
-                        <attr name="position" intvalue="850"/>
-                    </file>
-                    <file name="org-netbeans-modules-gsf-testrunner-TestMethodDebuggerAction.shadow">
-                        <attr name="originalFile" stringvalue="Actions/CommonTestRunner/org-netbeans-modules-gsf-testrunner-TestMethodDebuggerAction.instance"/>
-                        <attr name="position" intvalue="860"/>
-                    </file>
                 </folder>
                 <folder name="GlyphGutterActions">
                     <file name="org-netbeans-modules-debugger-ui-actions-ToggleBreakpointAction.shadow">
@@ -53,5 +38,5 @@
                 </folder>
             </folder>
         </folder>
-    </folder>  
+    </folder>
 </filesystem>
diff --git a/groovy/groovy.editor/nbproject/project.xml b/groovy/groovy.editor/nbproject/project.xml
index 5a5cbddee6..15a4adf66d 100644
--- a/groovy/groovy.editor/nbproject/project.xml
+++ b/groovy/groovy.editor/nbproject/project.xml
@@ -503,6 +503,7 @@
                 </test-type>
             </test-dependencies>
             <friend-packages>
+                <friend>org.netbeans.modules.groovy.debug</friend>
                 <friend>org.netbeans.modules.groovy.grailsproject</friend>
                 <friend>org.netbeans.modules.groovy.gsp</friend>
                 <friend>org.netbeans.modules.groovy.refactoring</friend>
diff --git a/groovy/groovy.kit/nbproject/project.xml b/groovy/groovy.kit/nbproject/project.xml
index 88a7269d60..d28972ba29 100644
--- a/groovy/groovy.kit/nbproject/project.xml
+++ b/groovy/groovy.kit/nbproject/project.xml
@@ -32,6 +32,13 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>org.netbeans.modules.groovy.debug</code-name-base>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+		<dependency>
                     <code-name-base>org.netbeans.modules.groovy.editor</code-name-base>
                     <run-dependency>
                         <release-version>3</release-version>
diff --git a/groovy/groovy.support/nbproject/project.xml b/groovy/groovy.support/nbproject/project.xml
index bb857af0b7..09265e81b3 100644
--- a/groovy/groovy.support/nbproject/project.xml
+++ b/groovy/groovy.support/nbproject/project.xml
@@ -264,24 +264,6 @@
                         <specification-version>1.18</specification-version>
                     </run-dependency>
                 </dependency>
-                <dependency>
-                    <code-name-base>org.netbeans.spi.debugger.ui</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <release-version>1</release-version>
-                        <specification-version>2.13</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.netbeans.spi.viewmodel</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <release-version>2</release-version>
-                        <specification-version>1.15</specification-version>
-                    </run-dependency>
-                </dependency>
                 <dependency>
                     <code-name-base>org.openide.actions</code-name-base>
                     <build-prerequisite/>
diff --git a/groovy/groovy.support/src/META-INF.debugger.BreakpointsView/org.netbeans.spi.viewmodel.NodeActionsProviderFilter b/groovy/groovy.support/src/META-INF.debugger.BreakpointsView/org.netbeans.spi.viewmodel.NodeActionsProviderFilter
deleted file mode 100644
index 9453cc9e8f..0000000000
--- a/groovy/groovy.support/src/META-INF.debugger.BreakpointsView/org.netbeans.spi.viewmodel.NodeActionsProviderFilter
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-org.netbeans.modules.groovy.support.debug.GroovyBreakpointActionsProvider
diff --git a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyLineBreakpointFactory.java b/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyLineBreakpointFactory.java
deleted file mode 100644
index 8e98de6778..0000000000
--- a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/debug/GroovyLineBreakpointFactory.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.groovy.support.debug;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import org.netbeans.api.debugger.jpda.LineBreakpoint;
-import org.netbeans.api.java.classpath.ClassPath;
-import static org.netbeans.modules.groovy.support.debug.Bundle.*;
-import org.openide.filesystems.FileObject;
-import org.openide.filesystems.FileUtil;
-import org.openide.filesystems.URLMapper;
-import org.openide.util.NbBundle.Messages;
-
-/**
- * Factory for creating new Groovy line breakpoints.
- * 
- * @author Martin Janicek
- */
-public class GroovyLineBreakpointFactory {
-
-    private static final Logger LOGGER = Logger.getLogger(GroovyLineBreakpointFactory.class.getName());
-    
-    
-    private GroovyLineBreakpointFactory() {
-    }
-
-    /**
-     * Creates a new breakpoint for the given parameters.
-     *
-     * @param url a url
-     * @param lineNumber a line number
-     * @return a new breakpoint for given parameters
-     */
-    @Messages("CTL_Default_Print_Text=Breakpoint reached at line {lineNumber} in {groovyName} by thread {threadName}.")
-    public static LineBreakpoint create(String url, int lineNumber) {
-        String pt = CTL_Default_Print_Text();
-        String printText = pt.replace("{groovyName}", getGroovyName(url));
-
-        LineBreakpoint groovyBreakpoint = LineBreakpoint.create(url, lineNumber);
-        groovyBreakpoint.setStratum("Groovy"); // NOI18N
-        groovyBreakpoint.setSourceName(getGroovyName(url));
-        groovyBreakpoint.setSourcePath(getGroovyPath(url));
-        groovyBreakpoint.setPreferredClassName(getClassFilter(url));
-        groovyBreakpoint.setPrintText(printText);
-        groovyBreakpoint.setHidden(false);
-
-        return groovyBreakpoint;
-    }
-
-    private static FileObject getFileObjectFromUrl(String url) {
-
-        FileObject fo = null;
-
-        try {
-            fo = URLMapper.findFileObject(new URL(url));
-        } catch (MalformedURLException e) {
-            //noop
-        }
-        return fo;
-    }
-
-    private static String getClassFilter(String url) {
-        String relativePath = getGroovyPath(url);
-        if (relativePath == null) {
-            return "";
-        }
-
-        if (relativePath.endsWith(".groovy")) { // NOI18N
-            relativePath = relativePath.substring(0, relativePath.length() - 7);
-        }
-        return relativePath.replace('/', '.') + "*";
-    }
-
-    private static String getGroovyName(String url) {
-        FileObject fo = getFileObjectFromUrl(url);
-        if (fo != null) {
-            return fo.getNameExt();
-        }
-        return (url == null) ? null : url.toString();
-    }
-
-    private static String getGroovyPath(String url) {
-        FileObject fo = getFileObjectFromUrl(url);
-        String relativePath = url;
-
-        if (fo != null) {
-            ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
-            if (cp == null) {
-                LOGGER.log(Level.FINE, "No classpath for {0}", url);
-                return null;
-            }
-            FileObject root = cp.findOwnerRoot(fo);
-            if (root == null) {
-                return null;
-            }
-            relativePath = FileUtil.getRelativePath(root, fo);
-        }
-
-        return relativePath;
-    }
-}
diff --git a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/resources/layer.xml b/groovy/groovy.support/src/org/netbeans/modules/groovy/support/resources/layer.xml
index d5cdc61f7e..ad3fd0c363 100644
--- a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/resources/layer.xml
+++ b/groovy/groovy.support/src/org/netbeans/modules/groovy/support/resources/layer.xml
@@ -32,10 +32,6 @@
         <folder name="text">
             <folder name="x-groovy">
                 <folder name="Popup">
-                    <file name="org-netbeans-modules-debugger-ui-actions-ToggleBreakpointAction.shadow">
-                        <attr name="originalFile" stringvalue="Actions/Debug/org-netbeans-modules-debugger-ui-actions-ToggleBreakpointAction.instance"/>
-                        <attr name="position" intvalue="1750"/>
-                    </file>
                     <file name="org-netbeans-modules-gsf-testrunner-TestMethodRunnerAction.shadow">
                         <attr name="originalFile" stringvalue="Actions/CommonTestRunner/org-netbeans-modules-gsf-testrunner-TestMethodRunnerAction.instance"/>
                         <attr name="position" intvalue="850"/>
@@ -45,13 +41,7 @@
                         <attr name="position" intvalue="860"/>
                     </file>
                 </folder>
-                <folder name="GlyphGutterActions">
-                    <file name="org-netbeans-modules-debugger-ui-actions-ToggleBreakpointAction.shadow">
-                        <attr name="originalFile" stringvalue="Actions/Debug/org-netbeans-modules-debugger-ui-actions-ToggleBreakpointAction.instance"/>
-                        <attr name="position" intvalue="500"/>
-                    </file>
-                </folder>
             </folder>
         </folder>
-    </folder>  
+    </folder>
 </filesystem>
diff --git a/groovy/libs.groovy/nbproject/project.xml b/groovy/libs.groovy/nbproject/project.xml
index 4c7671621f..ee6e1a6dc8 100644
--- a/groovy/libs.groovy/nbproject/project.xml
+++ b/groovy/libs.groovy/nbproject/project.xml
@@ -26,6 +26,7 @@
             <code-name-base>org.netbeans.modules.libs.groovy</code-name-base>
             <module-dependencies/>
             <friend-packages>
+                <friend>org.netbeans.modules.groovy.debug</friend>
                 <friend>org.netbeans.modules.groovy.editor</friend>
                 <friend>org.netbeans.modules.groovy.refactoring</friend>
                 <friend>org.netbeans.modules.groovy.support</friend>
diff --git a/java/api.debugger.jpda/apichanges.xml b/java/api.debugger.jpda/apichanges.xml
index 69574ef8e0..35bac69762 100644
--- a/java/api.debugger.jpda/apichanges.xml
+++ b/java/api.debugger.jpda/apichanges.xml
@@ -975,6 +975,20 @@ These are mainly class and thread filters and hit counts.
         <class package="org.netbeans.api.debugger.jpda" name="JPDAStep" />
         <class package="org.netbeans.api.debugger.jpda" name="JPDADebugger" />
     </change>
+
+    <change>
+        <api name="JPDADebuggerAPI"/>
+        <summary>BreakpointStratifier interface added.</summary>
+        <version major="3" minor="27"/>
+        <date day="26" month="5" year="2022"/>
+        <author login="mentlicher"/>
+        <compatibility addition="yes" source="compatible" binary="compatible"/>
+        <description>
+            <code>BreakpointStratifier</code> interface added to be able to adjust breakpoint properties
+            of newly created breakpoints according to the strata it belongs to.
+        </description>
+        <class package="org.netbeans.spi.debugger.jpda" name="BreakpointStratifier" />
+    </change>
 </changes>
 
   <!-- Now the surrounding HTML text and document structure: -->
diff --git a/java/api.debugger.jpda/manifest.mf b/java/api.debugger.jpda/manifest.mf
index 887d484f9f..1590bf59b0 100644
--- a/java/api.debugger.jpda/manifest.mf
+++ b/java/api.debugger.jpda/manifest.mf
@@ -1,6 +1,6 @@
 Manifest-Version: 1.0
 OpenIDE-Module: org.netbeans.api.debugger.jpda/2
 OpenIDE-Module-Localizing-Bundle: org/netbeans/api/debugger/jpda/Bundle.properties
-OpenIDE-Module-Specification-Version: 3.26
+OpenIDE-Module-Specification-Version: 3.27
 OpenIDE-Module-Package-Dependencies: com.sun.jdi[VirtualMachineManager]
 
diff --git a/java/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/LineBreakpoint.java b/java/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/LineBreakpoint.java
index 6be370fba2..a2d9cabef3 100644
--- a/java/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/LineBreakpoint.java
+++ b/java/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/LineBreakpoint.java
@@ -36,12 +36,14 @@ import org.netbeans.api.debugger.DebuggerEngine;
 import org.netbeans.api.debugger.DebuggerManager;
 import org.netbeans.api.project.Project;
 import org.netbeans.api.project.ProjectManager;
+import org.netbeans.spi.debugger.jpda.BreakpointStratifier;
 import org.openide.filesystems.FileAttributeEvent;
 import org.openide.filesystems.FileChangeListener;
 import org.openide.filesystems.FileEvent;
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.FileRenameEvent;
 import org.openide.filesystems.URLMapper;
+import org.openide.util.Lookup;
 import org.openide.util.NbBundle;
 import org.openide.util.WeakListeners;
 
@@ -111,6 +113,12 @@ public class LineBreakpoint extends JPDABreakpoint {
     ) {
         LineBreakpoint b = new LineBreakpointImpl (url);
         b.setLineNumber (lineNumber);
+        if (url != null && !url.isEmpty()) {
+            Collection<? extends BreakpointStratifier> stratifiers = Lookup.getDefault().lookupAll(BreakpointStratifier.class);
+            for (BreakpointStratifier stratifier : stratifiers) {
+                stratifier.stratify(b);
+            }
+        }
         return b;
     }
 
diff --git a/java/api.debugger.jpda/src/org/netbeans/spi/debugger/jpda/BreakpointStratifier.java b/java/api.debugger.jpda/src/org/netbeans/spi/debugger/jpda/BreakpointStratifier.java
new file mode 100644
index 0000000000..6da837881b
--- /dev/null
+++ b/java/api.debugger.jpda/src/org/netbeans/spi/debugger/jpda/BreakpointStratifier.java
@@ -0,0 +1,52 @@
+/*
+ * 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.spi.debugger.jpda;
+
+import org.netbeans.api.debugger.jpda.JPDABreakpoint;
+import org.netbeans.api.debugger.jpda.LineBreakpoint;
+
+/**
+ * Implement this interface to adjust breakpoint properties of newly created
+ * breakpoints according to the strata.
+ * <p>
+ * By default, breakpoints created via static methods like
+ * {@link LineBreakpoint#create(String, int)}, etc. are targeted to the default
+ * Java stratum. When the breakpoint's location is in a different language,
+ * adjustments of it's properties might be necessary.
+ * <p>
+ * When an implementation of this interface is
+ * {@link org.openide.util.lookup.ServiceProvider registered into the lookup},
+ * it is called with newly created JPDA breakpoint. Depending on its current
+ * properties, the implementation can adapt the breakpoint to the language
+ * stratum as necessary.
+ * <p>
+ * Currently applies to creation of {@link LineBreakpoint} with non-empty URL only.
+ * It can be extended to other breakpoint types in the future.
+ *
+ * @author Martin Entlicher
+ * @since 3.27
+ */
+public interface BreakpointStratifier {
+
+    /**
+     * Adjust the breakpoint properties according to its specific language stratum.
+     * @param breakpoint the breakpoint to adjust.
+     */
+    void stratify(JPDABreakpoint breakpoint);
+}
diff --git a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsReader.java b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsReader.java
index 5e0d5515a2..d95bd805b8 100644
--- a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsReader.java
+++ b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsReader.java
@@ -105,10 +105,9 @@ public class BreakpointsReader implements Properties.Reader, PropertyChangeListe
         // Read both LineBreakpoint and LineBreakpoint$LineBreakpointImpl
         if (typeID.equals (LineBreakpoint.class.getName ()) ||
                 typeID.equals (LineBreakpoint.class.getName ()+"$LineBreakpointImpl")) {
-            LineBreakpoint lb = LineBreakpoint.create (
-                properties.getString (LineBreakpoint.PROP_URL, null),
-                properties.getInt (LineBreakpoint.PROP_LINE_NUMBER, 1)
-            );
+            LineBreakpoint lb = LineBreakpoint.create ("", 0);
+            lb.setURL(properties.getString (LineBreakpoint.PROP_URL, null));
+            lb.setLineNumber(properties.getInt (LineBreakpoint.PROP_LINE_NUMBER, 1));
             lb.setCondition (
                 properties.getString (LineBreakpoint.PROP_CONDITION, "")
             );
diff --git a/java/java.lsp.server/nbproject/project.xml b/java/java.lsp.server/nbproject/project.xml
index 7ba0260797..d312853acd 100644
--- a/java/java.lsp.server/nbproject/project.xml
+++ b/java/java.lsp.server/nbproject/project.xml
@@ -69,7 +69,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>2</release-version>
-                        <specification-version>3.16</specification-version>
+                        <specification-version>3.27</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/GroovyBreakpointFactory.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/GroovyBreakpointFactory.java
deleted file mode 100644
index eee3c1b16d..0000000000
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/GroovyBreakpointFactory.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.java.lsp.server.debugging.breakpoints;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.logging.Level;
-import org.netbeans.api.debugger.jpda.LineBreakpoint;
-import org.netbeans.api.java.classpath.ClassPath;
-import org.openide.filesystems.FileObject;
-import org.openide.filesystems.FileUtil;
-import org.openide.filesystems.URLMapper;
-import org.openide.util.NbBundle;
-
-/**
- * Creates Groovy breakpoints.
- */
-public class GroovyBreakpointFactory {
-
-    private GroovyBreakpointFactory() {}
-
-    public static LineBreakpoint create(String url, int lineNumber) {
-        LineBreakpoint groovyBreakpoint = LineBreakpoint.create(url, lineNumber);
-
-        groovyBreakpoint.setStratum("Groovy"); // NOI18N
-        FileObject fo = findFileObjectFromUrl(url);
-        String sourceName = setGroovySourceName(groovyBreakpoint, fo);
-        String sourcePath = setGroovySourcePath(groovyBreakpoint, fo);
-        setImplClassFilter(groovyBreakpoint, sourcePath);
-        setPrintText(groovyBreakpoint, sourceName);
-
-        return groovyBreakpoint;
-    }
-
-    private static FileObject findFileObjectFromUrl(String url) {
-        FileObject fo;
-        try {
-            fo = URLMapper.findFileObject(new URL(url));
-        } catch (MalformedURLException e) {
-            fo = null;
-        }
-        return fo;
-    }
-
-    private static void setImplClassFilter(LineBreakpoint b, String relativePath) {
-        if (relativePath != null) {
-            int dot = relativePath.lastIndexOf('.');
-            if (dot > 0) {
-                relativePath = relativePath.substring(0, dot);
-                String pattern = relativePath.replace('/', '.') + "*";
-                b.setPreferredClassName(pattern);
-            }
-        }
-    }
-
-    private static String setGroovySourceName(LineBreakpoint b, FileObject fo) {
-        if (fo != null) {
-            String name = fo.getNameExt();
-            b.setSourceName(name);
-            return name;
-        }
-        return null;
-    }
-    private static String setGroovySourcePath(LineBreakpoint b, FileObject fo) {
-        if (fo != null) {
-            ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
-            if (cp != null) {
-                FileObject root = cp.findOwnerRoot(fo);
-                if (root != null) {
-                    String relativePath = FileUtil.getRelativePath(root, fo);
-                    b.setSourcePath(relativePath);
-                    return relativePath;
-                }
-            } else {
-                // Suppose the current folder
-                String relativePath = fo.getNameExt();
-                b.setSourcePath(relativePath);
-                return relativePath;
-            }
-        }
-        return null;
-    }
-
-    @NbBundle.Messages("CTL_Default_Print_Text=Breakpoint hit at line {lineNumber} in {groovyName} by thread {threadName}.")
-    private static void setPrintText(LineBreakpoint b, String sourceName) {
-        String printText;
-        if (sourceName != null) {
-            printText = Bundle.CTL_Default_Print_Text().replace("{groovyName}", sourceName); // NOI18N
-        } else {
-            printText = Bundle.CTL_Default_Print_Text().replace("{groovyName}", "?");        // NOI18N
-        }
-        b.setPrintText(printText);
-    }
-}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/NbBreakpoint.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/NbBreakpoint.java
index ca39974d2f..0c2e51b7ca 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/NbBreakpoint.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/NbBreakpoint.java
@@ -37,7 +37,6 @@ import org.netbeans.api.debugger.jpda.JPDABreakpoint;
 import org.netbeans.api.debugger.jpda.LineBreakpoint;
 import org.netbeans.modules.debugger.jpda.truffle.breakpoints.TruffleLineBreakpoint;
 import org.netbeans.modules.java.lsp.server.debugging.DebugAdapterContext;
-import org.openide.filesystems.URLMapper;
 
 /**
  *
@@ -105,12 +104,7 @@ public final class NbBreakpoint {
         boolean isJava = sourceURLLower.endsWith(".java");      // NOI18N
         boolean isGroovy = sourceURLLower.endsWith(".groovy");  // NOI18N
         if (isJava || isGroovy) {
-            LineBreakpoint b;
-            if (isJava) {
-                b = LineBreakpoint.create(sourceURL, line);
-            } else {
-                b = GroovyBreakpointFactory.create(sourceURL, line);
-            }
+            LineBreakpoint b = LineBreakpoint.create(sourceURL, line);
             if (condition != null && !condition.isEmpty()) {
                 b.setCondition(condition);
             }
diff --git a/nbbuild/cluster.properties b/nbbuild/cluster.properties
index ec87c9719b..a145e8af37 100644
--- a/nbbuild/cluster.properties
+++ b/nbbuild/cluster.properties
@@ -1027,6 +1027,7 @@ nb.cluster.groovy.depends=\
 nb.cluster.groovy=\
         gradle.groovy,\
         groovy.antproject,\
+        groovy.debug,\
         groovy.editor,\
         groovy.gsp,\
         groovy.kit,\


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

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