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

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


The following commit(s) were added to refs/heads/delivery by this push:
     new fc57ff6  [NETBEANS-4978] Avoid inserting use statements to an 
incorrect position
     new 9399810  Merge pull request #3279 from 
junichi11/netbeans-4978-wrong-insert-using-fix-import
fc57ff6 is described below

commit fc57ff6273b8aa603ef93ced3baae0c54d3641e7
Author: Junichi Yamamoto <junich...@apache.org>
AuthorDate: Wed Oct 27 20:46:22 2021 +0900

    [NETBEANS-4978] Avoid inserting use statements to an incorrect position
    
    - https://issues.apache.org/jira/browse/NETBEANS-4978
    
    This problem occurs when the caret position is not in a namespace scope.
    
    ```php
    // caret is here^
    declare (strict_types=1);
    
    namespace TestNamespace;
    
    class TestClass
    {
    
        public function __construct()
        {
            $test = new Foo();
        }
    
    }
    
    ```
    
    Before:
    ```php
    use Foo\Foo; // incorrect position
    // caret is here
    declare (strict_types=1);
    
    namespace TestNamespace;
    
    class TestClass
    {
    
        public function __construct()
        {
            $test = new Foo();
        }
    
    }
    
    ```
    
    After:
    ```php
    // caret is here
    declare (strict_types=1);
    
    namespace TestNamespace;
    
    use Foo\Foo; // correct position
    
    class TestClass
    {
    
        public function __construct()
        {
            $test = new Foo();
        }
    
    }
    
    ```
---
 .../modules/php/editor/actions/FixUsesAction.java  |  2 +-
 .../php/editor/actions/FixUsesPerformer.java       | 86 +++++++++++++++++--
 .../php/editor/actions/UsedNamesCollector.java     | 61 ++++++++++++-
 .../modules/php/editor/model/ModelUtils.java       | 99 ++++++++++++++++++++++
 .../test/unit/data/testfiles/actions/nb4978_01.php | 39 +++++++++
 .../data/testfiles/actions/nb4978_01.php.usedNames |  4 +
 .../test/unit/data/testfiles/actions/nb4978_02.php | 37 ++++++++
 .../data/testfiles/actions/nb4978_02.php.usedNames |  4 +
 .../test/unit/data/testfiles/actions/nb4978_03.php | 43 ++++++++++
 .../data/testfiles/actions/nb4978_03.php.usedNames |  4 +
 .../test/unit/data/testfiles/actions/nb4978_04.php | 45 ++++++++++
 .../data/testfiles/actions/nb4978_04.php.usedNames |  4 +
 .../test/unit/data/testfiles/actions/nb4978_05.php | 44 ++++++++++
 .../data/testfiles/actions/nb4978_05.php.usedNames |  4 +
 .../test/unit/data/testfiles/actions/nb4978_06.php | 44 ++++++++++
 .../data/testfiles/actions/nb4978_06.php.usedNames |  4 +
 .../test/unit/data/testfiles/actions/nb4978_07.php | 45 ++++++++++
 .../data/testfiles/actions/nb4978_07.php.usedNames |  4 +
 .../test/unit/data/testfiles/actions/nb4978_08.php | 50 +++++++++++
 .../data/testfiles/actions/nb4978_08.php.usedNames |  1 +
 .../actions/testNB4978/01/testNB4978_01.php        | 39 +++++++++
 .../testNB4978/01/testNB4978_01.php.fixUses        | 41 +++++++++
 .../actions/testNB4978/02/testNB4978_02.php        | 37 ++++++++
 .../testNB4978/02/testNB4978_02.php.fixUses        | 39 +++++++++
 .../actions/testNB4978/03/testNB4978_03.php        | 43 ++++++++++
 .../testNB4978/03/testNB4978_03.php.fixUses        | 45 ++++++++++
 .../actions/testNB4978/04/testNB4978_04.php        | 45 ++++++++++
 .../testNB4978/04/testNB4978_04.php.fixUses        | 47 ++++++++++
 .../actions/testNB4978/05/testNB4978_05.php        | 44 ++++++++++
 .../testNB4978/05/testNB4978_05.php.fixUses        | 46 ++++++++++
 .../actions/testNB4978/06/testNB4978_06.php        | 44 ++++++++++
 .../testNB4978/06/testNB4978_06.php.fixUses        | 46 ++++++++++
 .../actions/testNB4978/07/testNB4978_07.php        | 45 ++++++++++
 .../testNB4978/07/testNB4978_07.php.fixUses        | 47 ++++++++++
 .../php/editor/actions/FixUsesPerformerTest.java   | 42 +++++++++
 .../php/editor/actions/UsedNamesCollectorTest.java | 32 +++++++
 36 files changed, 1299 insertions(+), 7 deletions(-)

diff --git 
a/php/php.editor/src/org/netbeans/modules/php/editor/actions/FixUsesAction.java 
b/php/php.editor/src/org/netbeans/modules/php/editor/actions/FixUsesAction.java
index 076d077..f3563b9 100644
--- 
a/php/php.editor/src/org/netbeans/modules/php/editor/actions/FixUsesAction.java
+++ 
b/php/php.editor/src/org/netbeans/modules/php/editor/actions/FixUsesAction.java
@@ -155,7 +155,7 @@ public class FixUsesAction extends BaseAction {
     private static ImportData computeUses(final PHPParseResult parserResult, 
final int caretPosition) {
         Map<String, List<UsedNamespaceName>> filteredExistingNames = new 
UsedNamesCollector(parserResult, caretPosition).collectNames();
         Index index = parserResult.getModel().getIndexScope().getIndex();
-        NamespaceScope namespaceScope = 
ModelUtils.getNamespaceScope(parserResult.getModel().getFileScope(), 
caretPosition);
+        NamespaceScope namespaceScope = 
ModelUtils.getNamespaceScope(parserResult, caretPosition);
         assert namespaceScope != null;
         ImportData importData = new ImportDataCreator(filteredExistingNames, 
index, namespaceScope.getNamespaceName(), createOptions(parserResult)).create();
         importData.caretPosition = caretPosition;
diff --git 
a/php/php.editor/src/org/netbeans/modules/php/editor/actions/FixUsesPerformer.java
 
b/php/php.editor/src/org/netbeans/modules/php/editor/actions/FixUsesPerformer.java
index 32a1823..24dbcfd 100644
--- 
a/php/php.editor/src/org/netbeans/modules/php/editor/actions/FixUsesPerformer.java
+++ 
b/php/php.editor/src/org/netbeans/modules/php/editor/actions/FixUsesPerformer.java
@@ -34,6 +34,7 @@ import org.netbeans.api.lexer.TokenSequence;
 import org.netbeans.editor.BaseDocument;
 import org.netbeans.modules.csl.api.EditList;
 import org.netbeans.modules.csl.api.OffsetRange;
+import org.netbeans.modules.csl.spi.support.CancelSupport;
 import org.netbeans.modules.editor.indent.api.IndentUtils;
 import org.netbeans.modules.php.api.PhpVersion;
 import org.netbeans.modules.php.editor.CodeUtils;
@@ -53,10 +54,14 @@ import org.netbeans.modules.php.editor.model.UseScope;
 import org.netbeans.modules.php.editor.parser.PHPParseResult;
 import org.netbeans.modules.php.editor.parser.UnusedUsesCollector;
 import 
org.netbeans.modules.php.editor.parser.UnusedUsesCollector.UnusedOffsetRanges;
+import org.netbeans.modules.php.editor.parser.astnodes.DeclareStatement;
+import org.netbeans.modules.php.editor.parser.astnodes.NamespaceDeclaration;
 import org.netbeans.modules.php.editor.parser.astnodes.Program;
 import org.netbeans.modules.php.editor.parser.astnodes.UseStatement;
 import org.netbeans.modules.php.editor.parser.astnodes.visitors.DefaultVisitor;
+import org.openide.awt.StatusDisplayer;
 import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
 
 /**
  *
@@ -109,11 +114,12 @@ public class FixUsesPerformer {
         }
     }
 
+    @NbBundle.Messages("FixUsesPerformer.noChanges=Fix imports: No Changes")
     private void processSelections() {
         final List<ImportData.DataItem> dataItems = 
resolveDuplicateSelections();
-        NamespaceScope namespaceScope = 
ModelUtils.getNamespaceScope(parserResult.getModel().getFileScope(), 
importData.caretPosition);
+        NamespaceScope namespaceScope = 
ModelUtils.getNamespaceScope(parserResult, importData.caretPosition);
         assert namespaceScope != null;
-        int startOffset = getOffset(baseDocument, namespaceScope);
+        int startOffset = getOffset(baseDocument, namespaceScope, 
parserResult, importData.caretPosition);
         List<UsePart> useParts = new ArrayList<>();
         Collection<? extends GroupUseScope> declaredGroupUses = 
namespaceScope.getDeclaredGroupUses();
         for (GroupUseScope groupUseElement : declaredGroupUses) {
@@ -142,7 +148,13 @@ public class FixUsesPerformer {
             }
         }
         replaceUnimportedItems();
-        editList.replace(startOffset, 0, createInsertString(useParts), false, 
0);
+        String insertString = createInsertString(useParts);
+        // avoid being recognized as a modified file
+        if (insertString.isEmpty()) {
+            
StatusDisplayer.getDefault().setStatusText(Bundle.FixUsesPerformer_noChanges());
+        } else {
+            editList.replace(startOffset, 0, insertString, false, 0);
+        }
     }
 
     private void replaceUnimportedItems() {
@@ -428,7 +440,7 @@ public class FixUsesPerformer {
         return result;
     }
 
-    private static int getOffset(BaseDocument baseDocument, NamespaceScope 
namespaceScope) {
+    private static int getOffset(BaseDocument baseDocument, NamespaceScope 
namespaceScope, PHPParseResult parserResult, int caretPosition) {
         try {
             ModelElement lastSingleUse = getLastUse(namespaceScope, false);
             ModelElement lastGroupUse = getLastUse(namespaceScope, true);
@@ -447,7 +459,36 @@ public class FixUsesPerformer {
                 // XXX is this correct?
                 return LineDocumentUtils.getLineEnd(baseDocument, 
lastGroupUse.getNameRange().getEnd());
             }
-            return LineDocumentUtils.getLineEnd(baseDocument, 
namespaceScope.getOffset());
+            // NETBEANS-4978 check whether declare statemens exist
+            // e.g. in the following case, insert the code(use statements) 
after the declare statement
+            // declare (strict_types=1);
+            // class TestClass
+            // {
+            //     public function __construct()
+            //     {
+            //         $test = new Foo();
+            //     }
+            // }
+            int offset = LineDocumentUtils.getLineEnd(baseDocument, 
namespaceScope.getOffset());
+            CheckVisitor checkVisitor = new CheckVisitor();
+            parserResult.getProgram().accept(checkVisitor);
+            if (namespaceScope.isDefaultNamespace()) {
+                List<NamespaceDeclaration> globalNamespaceDeclarations = 
checkVisitor.getGlobalNamespaceDeclarations();
+                if (!globalNamespaceDeclarations.isEmpty()) {
+                    offset = 
globalNamespaceDeclarations.get(0).getBody().getStartOffset() + 1; // +1: {
+                }
+                for (NamespaceDeclaration globalNamespace : 
globalNamespaceDeclarations) {
+                    if (globalNamespace.getStartOffset() <= caretPosition
+                            && caretPosition <= 
globalNamespace.getEndOffset()) {
+                        offset = globalNamespace.getBody().getStartOffset() + 
1; // +1: {
+                        break;
+                    }
+                }
+            }
+            for (DeclareStatement declareStatement : 
checkVisitor.getDeclareStatements()) {
+                offset = Math.max(offset, declareStatement.getEndOffset());
+            }
+            return offset;
         } catch (BadLocationException ex) {
             Exceptions.printStackTrace(ex);
         }
@@ -467,6 +508,41 @@ public class FixUsesPerformer {
         return offsetElement;
     }
 
+    //~ inner classes
+    private static class CheckVisitor extends DefaultVisitor {
+
+        private List<DeclareStatement> declareStatements = new ArrayList();
+        private List<NamespaceDeclaration> globalNamespaceDeclarations = new 
ArrayList();
+
+        public List<DeclareStatement> getDeclareStatements() {
+            return Collections.unmodifiableList(declareStatements);
+        }
+
+        public List<NamespaceDeclaration> getGlobalNamespaceDeclarations() {
+            return Collections.unmodifiableList(globalNamespaceDeclarations);
+        }
+
+        @Override
+        public void visit(DeclareStatement node) {
+            if (CancelSupport.getDefault().isCancelled()) {
+                return;
+            }
+            declareStatements.add(node);
+            super.visit(node);
+        }
+
+        @Override
+        public void visit(NamespaceDeclaration declaration) {
+            if (CancelSupport.getDefault().isCancelled()) {
+                return;
+            }
+            if (declaration.isBracketed() && declaration.getName() == null) {
+                globalNamespaceDeclarations.add(declaration);
+            }
+            super.visit(declaration);
+        }
+    }
+
     private interface AliasStrategy {
         String createAlias(final QualifiedName qualifiedName);
     }
diff --git 
a/php/php.editor/src/org/netbeans/modules/php/editor/actions/UsedNamesCollector.java
 
b/php/php.editor/src/org/netbeans/modules/php/editor/actions/UsedNamesCollector.java
index b981b3f..e49b369 100644
--- 
a/php/php.editor/src/org/netbeans/modules/php/editor/actions/UsedNamesCollector.java
+++ 
b/php/php.editor/src/org/netbeans/modules/php/editor/actions/UsedNamesCollector.java
@@ -18,6 +18,7 @@
  */
 package org.netbeans.modules.php.editor.actions;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -25,6 +26,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import org.netbeans.modules.csl.api.OffsetRange;
+import org.netbeans.modules.csl.spi.support.CancelSupport;
 import org.netbeans.modules.php.editor.api.AliasedName;
 import org.netbeans.modules.php.editor.api.QualifiedName;
 import org.netbeans.modules.php.editor.model.ModelUtils;
@@ -33,6 +35,7 @@ import org.netbeans.modules.php.editor.model.UseScope;
 import org.netbeans.modules.php.editor.model.impl.Type;
 import org.netbeans.modules.php.editor.parser.PHPParseResult;
 import org.netbeans.modules.php.editor.parser.astnodes.ASTNode;
+import org.netbeans.modules.php.editor.parser.astnodes.Block;
 import org.netbeans.modules.php.editor.parser.astnodes.NamespaceDeclaration;
 import org.netbeans.modules.php.editor.parser.astnodes.NamespaceName;
 import org.netbeans.modules.php.editor.parser.astnodes.PHPDocTypeNode;
@@ -62,9 +65,45 @@ public class UsedNamesCollector {
     }
 
     public Map<String, List<UsedNamespaceName>> collectNames() {
-        NamespaceScope namespaceScope = 
ModelUtils.getNamespaceScope(parserResult.getModel().getFileScope(), 
caretPosition);
+        NamespaceScope namespaceScope = 
ModelUtils.getNamespaceScope(parserResult, caretPosition);
         assert namespaceScope != null;
         OffsetRange offsetRange = namespaceScope.getBlockRange();
+        // in the following case, avoid being inserted incorrect uses
+        // because default namespace range is whole file...
+        // // caret here^
+        // declare (strict_types=1);
+        //
+        // namespace {
+        //     class GlobalNamespace {}
+        // }
+        //
+        // namespace Test {
+        //     class TestClass {
+        //         public function __construct()
+        //         {
+        //             $test = new Foo();
+        //         }
+        //         public function test(?Foo $foo): ?Foo
+        //         {
+        //             return null;
+        //         }
+        //     }
+        // }
+        if (namespaceScope.isDefaultNamespace()) {
+            NamespaceDeclarationVisitor namespaceDeclarationVisitor = new 
NamespaceDeclarationVisitor();
+            parserResult.getProgram().accept(namespaceDeclarationVisitor);
+            List<NamespaceDeclaration> globalNamespaces = 
namespaceDeclarationVisitor.getGlobalNamespaceDeclarations();
+            if (!globalNamespaces.isEmpty()) {
+                Block body = globalNamespaces.get(0).getBody();
+                offsetRange = new OffsetRange(body.getStartOffset(), 
body.getEndOffset());
+            }
+            for (NamespaceDeclaration globalNamespace : globalNamespaces) {
+                if (globalNamespace.getBody().getStartOffset() <= caretPosition
+                        && caretPosition <= 
globalNamespace.getBody().getEndOffset()) {
+                    offsetRange = new 
OffsetRange(globalNamespace.getBody().getStartOffset(), 
globalNamespace.getBody().getEndOffset());
+                }
+            }
+        }
         Collection<? extends UseScope> declaredUses = 
namespaceScope.getAllDeclaredSingleUses();
         NamespaceNameVisitor namespaceNameVisitor = new 
NamespaceNameVisitor(offsetRange);
         parserResult.getProgram().accept(namespaceNameVisitor);
@@ -171,4 +210,24 @@ public class UsedNamesCollector {
 
     }
 
+    private static class NamespaceDeclarationVisitor extends DefaultVisitor {
+
+        private final List<NamespaceDeclaration> globalNamespaceDeclarations = 
new ArrayList<>();
+
+        public List<NamespaceDeclaration> getGlobalNamespaceDeclarations() {
+            return Collections.unmodifiableList(globalNamespaceDeclarations);
+        }
+
+        @Override
+        public void visit(NamespaceDeclaration node) {
+            if (CancelSupport.getDefault().isCancelled()) {
+                return;
+            }
+            if (node.isBracketed() && node.getName() == null) {
+                globalNamespaceDeclarations.add(node);
+            }
+            super.visit(node);
+        }
+
+    }
 }
diff --git 
a/php/php.editor/src/org/netbeans/modules/php/editor/model/ModelUtils.java 
b/php/php.editor/src/org/netbeans/modules/php/editor/model/ModelUtils.java
index ba45cf3..351f8a9 100644
--- a/php/php.editor/src/org/netbeans/modules/php/editor/model/ModelUtils.java
+++ b/php/php.editor/src/org/netbeans/modules/php/editor/model/ModelUtils.java
@@ -37,6 +37,7 @@ import org.netbeans.api.annotations.common.CheckForNull;
 import org.netbeans.api.annotations.common.NonNull;
 import org.netbeans.api.lexer.TokenSequence;
 import org.netbeans.modules.csl.api.OffsetRange;
+import org.netbeans.modules.csl.spi.support.CancelSupport;
 import org.netbeans.modules.parsing.api.ParserManager;
 import org.netbeans.modules.parsing.api.ResultIterator;
 import org.netbeans.modules.parsing.api.Source;
@@ -60,6 +61,7 @@ import 
org.netbeans.modules.php.editor.parser.astnodes.Expression;
 import org.netbeans.modules.php.editor.parser.astnodes.NamespaceDeclaration;
 import org.netbeans.modules.php.editor.parser.astnodes.StaticDispatch;
 import org.netbeans.modules.php.editor.parser.astnodes.VariableBase;
+import org.netbeans.modules.php.editor.parser.astnodes.visitors.DefaultVisitor;
 import org.openide.filesystems.FileObject;
 import org.openide.util.RequestProcessor;
 
@@ -424,6 +426,70 @@ public final class ModelUtils {
         return retval;
     }
 
+    public static NamespaceScope getNamespaceScope(PHPParseResult 
parserResult, int offset) {
+        // NETBEANS-4978
+        // if the caret position is not in each namespace scope, get the first 
namespace scope
+        // e.g.
+        // [original]
+        // // caret is here^
+        // declare (strict_types=1);
+        // namespace Foo;
+        // ...
+        // namespace Bar;
+        //
+        // [inserted]
+        // // caret is here
+        // declare (strict_types=1);
+        // namespace Foo;
+        // use ...;
+        // ...
+        // namespace Bar;
+        FileScope fileScope = parserResult.getModel().getFileScope();
+        List<NamespaceDeclaration> namespaceDeclarations = 
getNamespaceDeclarations(parserResult);
+        boolean isBracketed = false;
+        if (!namespaceDeclarations.isEmpty()) {
+            isBracketed = namespaceDeclarations.get(0).isBracketed();
+        }
+        NamespaceScope retval = ModelUtils.getNamespaceScope(fileScope, 
offset);
+        assert retval != null;
+        Collection<? extends NamespaceScope> declaredNamespaces = 
fileScope.getDeclaredNamespaces();
+        if (retval != null && retval.isDefaultNamespace()) {
+            // get the first namespace scope
+            if (isBracketed) {
+                for (NamespaceDeclaration namespaceDeclaration : 
namespaceDeclarations) {
+                    if (namespaceDeclaration.getName() == null
+                            && namespaceDeclaration.getStartOffset() <= offset 
&& offset <= namespaceDeclaration.getEndOffset()) {
+                        return retval;
+                    }
+                }
+                if (namespaceDeclarations.get(0).getName() == null) {
+                    return retval;
+                }
+                retval = getFirstNamespaceScope(declaredNamespaces, retval);
+            }
+            if (!isBracketed && !namespaceDeclarations.isEmpty()) {
+                // if namespace is not bracketed,
+                // both the global namespace and another namespace don't exist 
in the same file
+                retval = getFirstNamespaceScope(declaredNamespaces, retval);
+            }
+        }
+        return retval;
+    }
+
+    private static NamespaceScope getFirstNamespaceScope(Collection<? extends 
NamespaceScope> declaredNamespaces, NamespaceScope namespace) {
+        NamespaceScope retval = namespace;
+        for (NamespaceScope namespaceScope : declaredNamespaces) {
+            if (!namespaceScope.isDefaultNamespace()) {
+                if (retval.isDefaultNamespace()) {
+                    retval = namespaceScope;
+                } else if (retval.getBlockRange().getStart() > 
namespaceScope.getBlockRange().getStart()) {
+                    retval = namespaceScope;
+                }
+            }
+        }
+        return retval;
+    }
+
     @CheckForNull
     public static TypeScope getTypeScope(ModelElement element) {
         TypeScope retval = (element instanceof TypeScope) ? (TypeScope) 
element : null;
@@ -653,4 +719,37 @@ public final class ModelUtils {
         return scope instanceof FunctionScope
                 && ((FunctionScope) scope).isAnonymous();
     }
+
+    private static List<NamespaceDeclaration> 
getNamespaceDeclarations(PHPParseResult parserResult) {
+        NamespaceDeclarationVisitor checkVisitor = new 
NamespaceDeclarationVisitor();
+        parserResult.getProgram().accept(checkVisitor);
+        return checkVisitor.getNamespaceDeclarations();
+    }
+
+    private static class NamespaceDeclarationVisitor extends DefaultVisitor {
+
+        private final List<NamespaceDeclaration> namespaceDeclarations = new 
ArrayList<>();
+        private final List<NamespaceDeclaration> globalNamespaceDeclarations = 
new ArrayList<>();
+
+        public List<NamespaceDeclaration> getNamespaceDeclarations() {
+            return Collections.unmodifiableList(namespaceDeclarations);
+        }
+
+        public List<NamespaceDeclaration> getGlobalNamespaceDeclarations() {
+            return Collections.unmodifiableList(globalNamespaceDeclarations);
+        }
+
+        @Override
+        public void visit(NamespaceDeclaration node) {
+            if (CancelSupport.getDefault().isCancelled()) {
+                return;
+            }
+            namespaceDeclarations.add(node);
+            if (node.isBracketed() && node.getName() == null) {
+                globalNamespaceDeclarations.add(node);
+            }
+            super.visit(node);
+        }
+
+    }
 }
diff --git a/php/php.editor/test/unit/data/testfiles/actions/nb4978_01.php 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_01.php
new file mode 100644
index 0000000..8784f66
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_01.php
@@ -0,0 +1,39 @@
+<?php
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace TestNamespace;
+
+class TestClass
+{
+
+    public function __construct()
+    {
+        $test = new Foo();
+    }
+
+    public function test(?Foo $foo): ?Foo
+    {
+        return null;
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/nb4978_01.php.usedNames 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_01.php.usedNames
new file mode 100644
index 0000000..cb532de
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_01.php.usedNames
@@ -0,0 +1,4 @@
+Name: Foo
+ Foo --> Foo:955
+ Foo --> Foo:995
+ Foo --> Foo:1007
diff --git a/php/php.editor/test/unit/data/testfiles/actions/nb4978_02.php 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_02.php
new file mode 100644
index 0000000..dc45f22
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_02.php
@@ -0,0 +1,37 @@
+<?php
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+class TestClass
+{
+
+    public function __construct()
+    {
+        $test = new Foo();
+    }
+
+    public function test(?Foo $foo): ?Foo
+    {
+        return null;
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/nb4978_02.php.usedNames 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_02.php.usedNames
new file mode 100644
index 0000000..0c6fbf0
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_02.php.usedNames
@@ -0,0 +1,4 @@
+Name: Foo
+ Foo --> Foo:929
+ Foo --> Foo:969
+ Foo --> Foo:981
diff --git a/php/php.editor/test/unit/data/testfiles/actions/nb4978_03.php 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_03.php
new file mode 100644
index 0000000..f88eef9
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_03.php
@@ -0,0 +1,43 @@
+<?php
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace TestNamespace;
+
+class TestClass
+{
+
+    public function __construct()
+    {
+        $test = new Foo();
+    }
+
+    public function test(?Foo $foo): ?Foo
+    {
+        return null;
+    }
+
+}
+
+namespace Foo\Foo;
+
+class Foo {}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/nb4978_03.php.usedNames 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_03.php.usedNames
new file mode 100644
index 0000000..cb532de
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_03.php.usedNames
@@ -0,0 +1,4 @@
+Name: Foo
+ Foo --> Foo:955
+ Foo --> Foo:995
+ Foo --> Foo:1007
diff --git a/php/php.editor/test/unit/data/testfiles/actions/nb4978_04.php 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_04.php
new file mode 100644
index 0000000..db1dca2
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_04.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace Test {
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
+
+namespace Foo\Foo {
+    class Foo {}
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/nb4978_04.php.usedNames 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_04.php.usedNames
new file mode 100644
index 0000000..c4fcf1a
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_04.php.usedNames
@@ -0,0 +1,4 @@
+Name: Foo
+ Foo --> Foo:964
+ Foo --> Foo:1012
+ Foo --> Foo:1024
diff --git a/php/php.editor/test/unit/data/testfiles/actions/nb4978_05.php 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_05.php
new file mode 100644
index 0000000..faa032d
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_05.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * 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.
+ */
+
+declare (strict_types=1);
+
+namespace Foo\Foo {
+    class Foo {}
+}
+
+namespace Test {
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/nb4978_05.php.usedNames 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_05.php.usedNames
new file mode 100644
index 0000000..32d6efa
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_05.php.usedNames
@@ -0,0 +1,4 @@
+Name: Foo
+ Foo --> Foo:996
+ Foo --> Foo:1044
+ Foo --> Foo:1056
diff --git a/php/php.editor/test/unit/data/testfiles/actions/nb4978_06.php 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_06.php
new file mode 100644
index 0000000..de34c1d
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_06.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * 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.
+ */
+
+declare (strict_types=1);
+
+namespace Foo\Foo {
+    class Foo {}
+}
+
+namespace {
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/nb4978_06.php.usedNames 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_06.php.usedNames
new file mode 100644
index 0000000..f434dda
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_06.php.usedNames
@@ -0,0 +1,4 @@
+Name: Foo
+ Foo --> Foo:991
+ Foo --> Foo:1039
+ Foo --> Foo:1051
diff --git a/php/php.editor/test/unit/data/testfiles/actions/nb4978_07.php 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_07.php
new file mode 100644
index 0000000..2c9bb96
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_07.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace {
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
+
+namespace Foo\Foo {
+    class Foo {}
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/nb4978_07.php.usedNames 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_07.php.usedNames
new file mode 100644
index 0000000..a46893c
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_07.php.usedNames
@@ -0,0 +1,4 @@
+Name: Foo
+ Foo --> Foo:959
+ Foo --> Foo:1007
+ Foo --> Foo:1019
diff --git a/php/php.editor/test/unit/data/testfiles/actions/nb4978_08.php 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_08.php
new file mode 100644
index 0000000..9e4d4c4
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_08.php
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace {
+    class GlobalNamespace {
+    }
+}
+
+namespace Foo\Foo {
+    class Foo {}
+}
+
+namespace Test {
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/nb4978_08.php.usedNames 
b/php/php.editor/test/unit/data/testfiles/actions/nb4978_08.php.usedNames
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/php/php.editor/test/unit/data/testfiles/actions/nb4978_08.php.usedNames
@@ -0,0 +1 @@
+
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/01/testNB4978_01.php
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/01/testNB4978_01.php
new file mode 100644
index 0000000..8784f66
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/01/testNB4978_01.php
@@ -0,0 +1,39 @@
+<?php
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace TestNamespace;
+
+class TestClass
+{
+
+    public function __construct()
+    {
+        $test = new Foo();
+    }
+
+    public function test(?Foo $foo): ?Foo
+    {
+        return null;
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/01/testNB4978_01.php.fixUses
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/01/testNB4978_01.php.fixUses
new file mode 100644
index 0000000..6e16892
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/01/testNB4978_01.php.fixUses
@@ -0,0 +1,41 @@
+<?php
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace TestNamespace;
+
+use Foo\Foo\Foo;
+
+class TestClass
+{
+
+    public function __construct()
+    {
+        $test = new Foo();
+    }
+
+    public function test(?Foo $foo): ?Foo
+    {
+        return null;
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/02/testNB4978_02.php
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/02/testNB4978_02.php
new file mode 100644
index 0000000..dc45f22
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/02/testNB4978_02.php
@@ -0,0 +1,37 @@
+<?php
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+class TestClass
+{
+
+    public function __construct()
+    {
+        $test = new Foo();
+    }
+
+    public function test(?Foo $foo): ?Foo
+    {
+        return null;
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/02/testNB4978_02.php.fixUses
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/02/testNB4978_02.php.fixUses
new file mode 100644
index 0000000..1c7fb03
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/02/testNB4978_02.php.fixUses
@@ -0,0 +1,39 @@
+<?php
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+use Foo\Foo\Foo;
+
+class TestClass
+{
+
+    public function __construct()
+    {
+        $test = new Foo();
+    }
+
+    public function test(?Foo $foo): ?Foo
+    {
+        return null;
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/03/testNB4978_03.php
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/03/testNB4978_03.php
new file mode 100644
index 0000000..f88eef9
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/03/testNB4978_03.php
@@ -0,0 +1,43 @@
+<?php
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace TestNamespace;
+
+class TestClass
+{
+
+    public function __construct()
+    {
+        $test = new Foo();
+    }
+
+    public function test(?Foo $foo): ?Foo
+    {
+        return null;
+    }
+
+}
+
+namespace Foo\Foo;
+
+class Foo {}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/03/testNB4978_03.php.fixUses
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/03/testNB4978_03.php.fixUses
new file mode 100644
index 0000000..783faf5
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/03/testNB4978_03.php.fixUses
@@ -0,0 +1,45 @@
+<?php
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace TestNamespace;
+
+use Foo\Foo\Foo;
+
+class TestClass
+{
+
+    public function __construct()
+    {
+        $test = new Foo();
+    }
+
+    public function test(?Foo $foo): ?Foo
+    {
+        return null;
+    }
+
+}
+
+namespace Foo\Foo;
+
+class Foo {}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/04/testNB4978_04.php
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/04/testNB4978_04.php
new file mode 100644
index 0000000..db1dca2
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/04/testNB4978_04.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace Test {
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
+
+namespace Foo\Foo {
+    class Foo {}
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/04/testNB4978_04.php.fixUses
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/04/testNB4978_04.php.fixUses
new file mode 100644
index 0000000..d3049ef
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/04/testNB4978_04.php.fixUses
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace Test {
+
+use Foo\Foo\Foo;
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
+
+namespace Foo\Foo {
+    class Foo {}
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/05/testNB4978_05.php
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/05/testNB4978_05.php
new file mode 100644
index 0000000..faa032d
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/05/testNB4978_05.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * 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.
+ */
+
+declare (strict_types=1);
+
+namespace Foo\Foo {
+    class Foo {}
+}
+
+namespace Test {
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/05/testNB4978_05.php.fixUses
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/05/testNB4978_05.php.fixUses
new file mode 100644
index 0000000..02ad4b4
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/05/testNB4978_05.php.fixUses
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * 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.
+ */
+
+declare (strict_types=1);
+
+namespace Foo\Foo {
+    class Foo {}
+}
+
+namespace Test {
+
+use Foo\Foo\Foo;
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/06/testNB4978_06.php
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/06/testNB4978_06.php
new file mode 100644
index 0000000..de34c1d
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/06/testNB4978_06.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * 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.
+ */
+
+declare (strict_types=1);
+
+namespace Foo\Foo {
+    class Foo {}
+}
+
+namespace {
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/06/testNB4978_06.php.fixUses
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/06/testNB4978_06.php.fixUses
new file mode 100644
index 0000000..84041bd
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/06/testNB4978_06.php.fixUses
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * 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.
+ */
+
+declare (strict_types=1);
+
+namespace Foo\Foo {
+    class Foo {}
+}
+
+namespace {
+
+use Foo\Foo\Foo;
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/07/testNB4978_07.php
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/07/testNB4978_07.php
new file mode 100644
index 0000000..2c9bb96
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/07/testNB4978_07.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace {
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
+
+namespace Foo\Foo {
+    class Foo {}
+}
diff --git 
a/php/php.editor/test/unit/data/testfiles/actions/testNB4978/07/testNB4978_07.php.fixUses
 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/07/testNB4978_07.php.fixUses
new file mode 100644
index 0000000..2f656c1
--- /dev/null
+++ 
b/php/php.editor/test/unit/data/testfiles/actions/testNB4978/07/testNB4978_07.php.fixUses
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * 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.
+ */
+
+// test
+declare (strict_types=1);
+
+namespace {
+
+use Foo\Foo\Foo;
+
+    class TestClass {
+
+        public function __construct()
+        {
+            $test = new Foo();
+        }
+
+        public function test(?Foo $foo): ?Foo
+        {
+            return null;
+        }
+
+    }
+
+}
+
+namespace Foo\Foo {
+    class Foo {}
+}
diff --git 
a/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/actions/FixUsesPerformerTest.java
 
b/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/actions/FixUsesPerformerTest.java
index b5400c8..7518c87 100644
--- 
a/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/actions/FixUsesPerformerTest.java
+++ 
b/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/actions/FixUsesPerformerTest.java
@@ -310,6 +310,48 @@ public class FixUsesPerformerTest extends PHPTestBase {
         performTest("$f = f($someVar);^", selections, false, options);
     }
 
+    public void testNB4978_01() throws Exception {
+        String[] selections = new String[] {"\\Foo\\Foo\\Foo"};
+        Options options = new Options(false, false, false, false, true);
+        performTest("// test^", createSelections(selections, 
ItemVariant.Type.CLASS), true, options);
+    }
+
+    public void testNB4978_02() throws Exception {
+        String[] selections = new String[] {"\\Foo\\Foo\\Foo"};
+        Options options = new Options(false, false, false, false, true);
+        performTest("// test^", createSelections(selections, 
ItemVariant.Type.CLASS), true, options);
+    }
+
+    public void testNB4978_03() throws Exception {
+        String[] selections = new String[] {"\\Foo\\Foo\\Foo"};
+        Options options = new Options(false, false, false, false, true);
+        performTest("// test^", createSelections(selections, 
ItemVariant.Type.CLASS), true, options);
+    }
+
+    public void testNB4978_04() throws Exception {
+        String[] selections = new String[] {"\\Foo\\Foo\\Foo"};
+        Options options = new Options(false, false, false, false, true);
+        performTest("// test^", createSelections(selections, 
ItemVariant.Type.CLASS), true, options);
+    }
+
+    public void testNB4978_05() throws Exception {
+        String[] selections = new String[] {"\\Foo\\Foo\\Foo"};
+        Options options = new Options(false, false, false, false, true);
+        performTest("public funct^ion test(?Foo $foo): ?Foo", 
createSelections(selections, ItemVariant.Type.CLASS), true, options);
+    }
+
+    public void testNB4978_06() throws Exception {
+        String[] selections = new String[] {"\\Foo\\Foo\\Foo"};
+        Options options = new Options(false, false, false, false, true);
+        performTest("public funct^ion test(?Foo $foo): ?Foo", 
createSelections(selections, ItemVariant.Type.CLASS), true, options);
+    }
+
+    public void testNB4978_07() throws Exception {
+        String[] selections = new String[] {"\\Foo\\Foo\\Foo"};
+        Options options = new Options(false, false, false, false, true);
+        performTest("// test^", createSelections(selections, 
ItemVariant.Type.CLASS), true, options);
+    }
+
     private String getTestResult(final String fileName, final String 
caretLine, final List<Selection> selections, final boolean removeUnusedUses, 
final Options options) throws Exception {
         FileObject testFile = getTestFile(fileName);
 
diff --git 
a/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/actions/UsedNamesCollectorTest.java
 
b/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/actions/UsedNamesCollectorTest.java
index 7f46287..09dcb46 100644
--- 
a/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/actions/UsedNamesCollectorTest.java
+++ 
b/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/actions/UsedNamesCollectorTest.java
@@ -80,6 +80,38 @@ public class UsedNamesCollectorTest extends PHPTestBase {
         performTest("issue209755", "class Class^Name {");
     }
 
+    public void testNB4978_01() throws Exception {
+        performTest("nb4978_01", "// test^");
+    }
+
+    public void testNB4978_02() throws Exception {
+        performTest("nb4978_02", "// test^");
+    }
+
+    public void testNB4978_03() throws Exception {
+        performTest("nb4978_03", "// test^");
+    }
+
+    public void testNB4978_04() throws Exception {
+        performTest("nb4978_04", "// test^");
+    }
+
+    public void testNB4978_05() throws Exception {
+        performTest("nb4978_05", "public funct^ion test(?Foo $foo): ?Foo");
+    }
+
+    public void testNB4978_06() throws Exception {
+        performTest("nb4978_06", "public funct^ion test(?Foo $foo): ?Foo");
+    }
+
+    public void testNB4978_07() throws Exception {
+        performTest("nb4978_07", "// test^");
+    }
+
+    public void testNB4978_08() throws Exception {
+        performTest("nb4978_08", "// test^");
+    }
+
     protected void performTest(String fileName, String caretLine) throws 
Exception {
         String exactFileName = "testfiles/actions/" + fileName + ".php";
         Map<String, List<UsedNamespaceName>> testResult = 
getTestResult(exactFileName, caretLine);

---------------------------------------------------------------------
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