Skip to content

Commit

Permalink
[NETBEANS-501] Support (clone $object)->method() in PHP
Browse files Browse the repository at this point in the history
- Restore the current token sequence offset to the clone expression end offset when `clone` keyword is found
  • Loading branch information
junichi11 committed Aug 17, 2019
1 parent 2f16e2e commit a77ee5f
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,7 @@ public static String getSemiType(TokenSequence<PHPTokenId> tokenSequence, State
int leftBraces = 0;
int rightBraces = State.PARAMS.equals(state) ? 1 : 0;
int arrayBrackets = 0;
CloneExpressionInfo cloneInfo = new CloneExpressionInfo();
StringBuilder metaAll = new StringBuilder();
while (!state.equals(State.INVALID) && !state.equals(State.STOP) && tokenSequence.movePrevious() && skipWhitespaces(tokenSequence)) {
Token<PHPTokenId> token = tokenSequence.token();
Expand All @@ -1104,9 +1105,11 @@ public static String getSemiType(TokenSequence<PHPTokenId> tokenSequence, State
if (isReference(token)) {
metaAll.insert(0, PRE_OPERATION_TYPE_DELIMITER + VariousUtils.METHOD_TYPE_PREFIX);
state = State.REFERENCE;
cloneInfo.setReference(state);
} else if (isStaticReference(token)) {
metaAll.insert(0, PRE_OPERATION_TYPE_DELIMITER + VariousUtils.METHOD_TYPE_PREFIX);
state = State.STATIC_REFERENCE;
cloneInfo.setReference(state);
} else if (state.equals(State.STOP)) {
metaAll.insert(0, PRE_OPERATION_TYPE_DELIMITER + VariousUtils.FUNCTION_TYPE_PREFIX);
}
Expand All @@ -1130,6 +1133,7 @@ public static String getSemiType(TokenSequence<PHPTokenId> tokenSequence, State
if (isRightBracket(token)) {
rightBraces++;
state = State.PARAMS;
cloneInfo.setEndOffset(tokenSequence.offset());
} else if (isRightArryBracket(token)) {
arrayBrackets++;
state = State.IDX;
Expand All @@ -1152,6 +1156,7 @@ public static String getSemiType(TokenSequence<PHPTokenId> tokenSequence, State
} else if (isRightBracket(token)) {
rightBraces++;
state = State.PARAMS;
cloneInfo.setEndOffset(tokenSequence.offset());
} else if (isRightArryBracket(token)) {
arrayBrackets++;
state = State.IDX;
Expand Down Expand Up @@ -1179,6 +1184,15 @@ public static String getSemiType(TokenSequence<PHPTokenId> tokenSequence, State
if (leftBraces == rightBraces) {
state = State.FUNCTION;
}
// NETBEANS-501
if (PHPTokenId.PHP_CLONE == token.id()
&& cloneInfo.getEndOffset() != -1
&& cloneInfo.getReference() != null) {
tokenSequence.move(cloneInfo.getEndOffset());
tokenSequence.moveNext();
state = cloneInfo.getReference();
rightBraces--;
}
break;
case FUNCTION:
state = State.INVALID;
Expand Down Expand Up @@ -1795,4 +1809,27 @@ public static boolean isStaticClassName(String className) {
public static boolean isSemiType(String typeName) {
return typeName != null && typeName.contains(PRE_OPERATION_TYPE_DELIMITER);
}

//~ inner class
private static class CloneExpressionInfo {

private int endOffset = -1;
private State reference = null;

public int getEndOffset() {
return endOffset;
}

public void setEndOffset(int endOffset) {
this.endOffset = endOffset;
}

public State getReference() {
return reference;
}

public void setReference(State reference) {
this.reference = reference;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?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 Example
{
public function __construct() {
}

public function testMethod() {
echo 'test' . PHP_EOL;
}

public static function getDefault() {
return new Example;
}
}

$example = new Example();
$example->testMethod();
(new Example())->testMethod();
(clone $example)-> // test 1
(clone Example::getDefault())->testMethod(); // test2
(clone Example::getDefault())::getDefault()->testMethod(); // test3
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Code completion result for source line:
(clone $example)->| // test 1
(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true)
METHOD getDefault() [STATIC] Example
METHOD testMethod() [PUBLIC] Example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Code completion result for source line:
(clone Example::getDefault())->|testMethod(); // test2
(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true)
METHOD getDefault() [STATIC] Example
METHOD testMethod() [PUBLIC] Example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Code completion result for source line:
(clone Example::getDefault())::|getDefault()->testMethod(); // test3
(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true)
METHOD getDefault() [STATIC] Example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Code completion result for source line:
(clone Example::getDefault())::getDefault()->|testMethod(); // test3
(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true)
METHOD getDefault() [STATIC] Example
METHOD testMethod() [PUBLIC] Example
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 PHPCodeCompletionNb501Test extends PHPCodeCompletionTestBase {

public PHPCodeCompletionNb501Test(String testName) {
super(testName);
}

public void testNb501_01() throws Exception {
checkCompletion("testfiles/completion/lib/nb501/nb501.php", "(clone $example)->^ // test 1", false);
}

public void testNb501_02() throws Exception {
checkCompletion("testfiles/completion/lib/nb501/nb501.php", "(clone Example::getDefault())->^testMethod(); // test2", false);
}

public void testNb501_03a() throws Exception {
checkCompletion("testfiles/completion/lib/nb501/nb501.php", "(clone Example::getDefault())::^getDefault()->testMethod(); // test3", false);
}

public void testNb501_03b() throws Exception {
checkCompletion("testfiles/completion/lib/nb501/nb501.php", "(clone Example::getDefault())::getDefault()->^testMethod(); // 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/nb501"))
})
);
}
}

0 comments on commit a77ee5f

Please sign in to comment.