This is an automated email from the ASF dual-hosted git repository. tmysik 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 acdaf52 [NETBEANS-2992] Code completion does not work well inside Closures new 2f16e2e Merge pull request #1434 from junichi11/netbeans-2992 acdaf52 is described below commit acdaf52d880133c6c9153c6caecb00f22cde47ff Author: Junichi Yamamoto <junich...@apache.org> AuthorDate: Fri Aug 16 21:35:45 2019 +0900 [NETBEANS-2992] Code completion does not work well inside Closures - Change the current scope when `$this` is used in anonymous functions --- .../modules/php/editor/model/ModelUtils.java | 12 ++++ .../php/editor/model/impl/ModelVisitor.java | 14 ++++- .../php/editor/model/impl/VariousUtils.java | 21 ++++++- .../testfiles/completion/lib/nb2992/nb2992.php | 70 ++++++++++++++++++++++ .../lib/nb2992/nb2992.php.testNb2992_01.completion | 4 ++ .../lib/nb2992/nb2992.php.testNb2992_02.completion | 4 ++ .../lib/nb2992/nb2992.php.testNb2992_03.completion | 4 ++ .../issue247082.php.testForKeywords.completion | 1 - .../completion/PHPCodeCompletionNb2992Test.java | 58 ++++++++++++++++++ 9 files changed, 185 insertions(+), 3 deletions(-) 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 869eced..d79558f 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 @@ -631,4 +631,16 @@ public final class ModelUtils { } return result; } + + /** + * Check whether the scope is anonymous function scope. + * + * @param scope the scope + * @return {@code true} if the scope is anonymous function scope, + * {@code false} otherwise + */ + public static boolean isAnonymousFunction(Scope scope) { + return scope instanceof FunctionScope + && ((FunctionScope) scope).isAnonymous(); + } } diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/ModelVisitor.java b/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/ModelVisitor.java index 90d6a7a..c9e38ae 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/ModelVisitor.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/ModelVisitor.java @@ -760,9 +760,21 @@ public final class ModelVisitor extends DefaultTreePathVisitor { return; } Scope scope = modelBuilder.getCurrentScope(); + ASTNodeInfo<Variable> varInfo = ASTNodeInfo.create(node); + // NETBEANS-2992 + // when $this is used in anonymous function, change the current scope + if (ModelUtils.isAnonymousFunction(scope) + && "$this".equals(varInfo.getName())) { // NOI18N + Scope inScope = scope.getInScope(); + while (!(inScope instanceof MethodScope) && inScope instanceof FunctionScope) { + inScope = inScope.getInScope(); + } + if (inScope instanceof MethodScope) { + scope = inScope; + } + } prepareVariable(node, scope); if (scope instanceof VariableNameFactory) { - ASTNodeInfo<Variable> varInfo = ASTNodeInfo.create(node); if (scope instanceof MethodScope && "$this".equals(varInfo.getName())) { //NOI18N scope = scope.getInScope(); } diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/VariousUtils.java b/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/VariousUtils.java index 432dce8..a6dd8c9 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/VariousUtils.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/model/impl/VariousUtils.java @@ -593,7 +593,7 @@ public final class VariousUtils { || (operation.startsWith(VariousUtils.ARRAY_TYPE_PREFIX))) { Set<TypeScope> newRecentTypes = new HashSet<>(); String varName = frag; - VariableName var = ModelUtils.getFirst(varScope.getDeclaredVariables(), varName); + VariableName var = getVariableName(varScope, varName); if (var != null) { if (i + 2 < len && VariousUtils.FIELD_TYPE_PREFIX.startsWith(fragments[i + 1])) { fldVarStack.push(var); @@ -684,6 +684,25 @@ public final class VariousUtils { return recentTypes; } + @CheckForNull + private static VariableName getVariableName(final VariableScope varScope, String varName) { + VariableName var = ModelUtils.getFirst(varScope.getDeclaredVariables(), varName); + // NETBEANS-2992 + // when $this is used in anonymous function, check the parent scope + if (var == null + && ModelUtils.isAnonymousFunction(varScope) + && varName.equals("$this")) { // NOI18N + Scope inScope = varScope.getInScope(); + while (ModelUtils.isAnonymousFunction(inScope)) { + inScope = inScope.getInScope(); + } + if (inScope instanceof VariableScope) { + var = ModelUtils.getFirst(((VariableScope) inScope).getDeclaredVariables(), varName); + } + } + return var; + } + private static Collection<TypeScope> filterSuperTypes(final Collection<? extends TypeScope> typeScopes) { final Collection<TypeScope> result = new HashSet<>(); if (typeScopes.size() > 1) { diff --git a/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php b/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php new file mode 100644 index 0000000..e6ff4c0 --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php @@ -0,0 +1,70 @@ +<?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. + */ +class Validator +{ + public function validate(\Closure $closure): void + { + $closure(); + } +} + +class Test +{ + public function testMethod(): void + { + echo "test" . PHP_EOL; + } +} + +class Example +{ + /** + * @var Validator + */ + private $validator; + /** + * @var Test + */ + private $test; + public function __construct() + { + $this->validator = new Validator; + $this->test = new Test; + } + public function main(): void + { + $this->validator->validate( + function () { + $this->test-> // test1 + }, + ); + $func = function () { + $this->test->testMethod(); // test2 + }; + $func(); + // PHP 7.4 Arrow Function + $func2 = fn() => $this->test->testMethod(); //test3 + $func2(); + } + +} + +$example = new Example(); +$example->main(); diff --git a/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php.testNb2992_01.completion b/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php.testNb2992_01.completion new file mode 100644 index 0000000..b7524c9 --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php.testNb2992_01.completion @@ -0,0 +1,4 @@ +Code completion result for source line: +$this->test->| // test1 +(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true) +METHOD testMethod() [PUBLIC] Test diff --git a/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php.testNb2992_02.completion b/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php.testNb2992_02.completion new file mode 100644 index 0000000..a244787 --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php.testNb2992_02.completion @@ -0,0 +1,4 @@ +Code completion result for source line: +$this->test->|testMethod(); // test2 +(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true) +METHOD testMethod() [PUBLIC] Test diff --git a/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php.testNb2992_03.completion b/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php.testNb2992_03.completion new file mode 100644 index 0000000..3dc5ebf --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/completion/lib/nb2992/nb2992.php.testNb2992_03.completion @@ -0,0 +1,4 @@ +Code completion result for source line: +$func2 = fn() => $this->test->test|Method(); //test3 +(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true) +METHOD testMethod() [PUBLIC] Test diff --git a/php/php.editor/test/unit/data/testfiles/completion/lib/tests247082/issue247082.php.testForKeywords.completion b/php/php.editor/test/unit/data/testfiles/completion/lib/tests247082/issue247082.php.testForKeywords.completion index 4114956..408116d 100644 --- a/php/php.editor/test/unit/data/testfiles/completion/lib/tests247082/issue247082.php.testForKeywords.completion +++ b/php/php.editor/test/unit/data/testfiles/completion/lib/tests247082/issue247082.php.testForKeywords.completion @@ -3,7 +3,6 @@ echo |self::MY_CONST . PHP_EOL; (QueryType=COMPLETION, prefixSearch=true, caseSensitive=true) CLASS A [PUBLIC] issue247082.php CLASS ParentA [PUBLIC] issue247082.php -VARIABLE ? $this [PUBLIC] issue247082.php VARIABLE ? $val [PUBLIC] issue247082.php KEYWORD A $this-> null KEYWORD parent:: null diff --git a/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/completion/PHPCodeCompletionNb2992Test.java b/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/completion/PHPCodeCompletionNb2992Test.java new file mode 100644 index 0000000..478d6e2 --- /dev/null +++ b/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/completion/PHPCodeCompletionNb2992Test.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.php.editor.completion; + +import java.io.File; +import java.util.Collections; +import java.util.Map; +import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.modules.php.project.api.PhpSourcePath; +import org.netbeans.spi.java.classpath.support.ClassPathSupport; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; + + +public class PHPCodeCompletionNb2992Test extends PHPCodeCompletionTestBase { + + public PHPCodeCompletionNb2992Test(String testName) { + super(testName); + } + + public void testNb2992_01() throws Exception { + checkCompletion("testfiles/completion/lib/nb2992/nb2992.php", "$this->test->^ // test1", false); + } + + public void testNb2992_02() throws Exception { + checkCompletion("testfiles/completion/lib/nb2992/nb2992.php", "$this->test->^testMethod(); // test2", false); + } + + public void testNb2992_03() throws Exception { + checkCompletion("testfiles/completion/lib/nb2992/nb2992.php", "$func2 = fn() => $this->test->test^Method(); //test3", false); + } + + @Override + protected Map<String, ClassPath> createClassPathsForTest() { + return Collections.singletonMap( + PhpSourcePath.SOURCE_CP, + ClassPathSupport.createClassPath(new FileObject[] { + FileUtil.toFileObject(new File(getDataDir(), "/testfiles/completion/lib/nb2992")) + }) + ); + } +} --------------------------------------------------------------------- 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