Skip to content

Commit

Permalink
Reimplement magic Prophecy method #8
Browse files Browse the repository at this point in the history
  • Loading branch information
Haehnchen committed May 2, 2017
1 parent e7fa620 commit d4219cb
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 2 deletions.
1 change: 1 addition & 0 deletions META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@

<extensions defaultExtensionNs="com.jetbrains.php">
<typeProvider3 implementation="de.espend.idea.php.phpunit.type.MockProphecyTypeProvider"/>
<typeProvider3 implementation="de.espend.idea.php.phpunit.type.ProphecyTypeProvider"/>
</extensions>

<extensions defaultExtensionNs="com.intellij">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
import java.util.*;

public class MockProphecyTypeProvider implements PhpTypeProvider3 {
private static char TRIM_KEY = '\u0192';
static final char CHAR = '元';
static char TRIM_KEY = '\u0192';

private static Collection<String> PHPUNIT_CLASSES = new HashSet<String>() {{
add("\\PHPUnit\\Framework\\TestCase");
Expand All @@ -38,7 +39,7 @@ public class MockProphecyTypeProvider implements PhpTypeProvider3 {

@Override
public char getKey() {
return '元';
return CHAR;
}

@Nullable
Expand Down
62 changes: 62 additions & 0 deletions src/de/espend/idea/php/phpunit/type/ProphecyTypeProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package de.espend.idea.php.phpunit.type;

import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.jetbrains.php.lang.psi.PhpPsiUtil;
import com.jetbrains.php.lang.psi.elements.*;
import com.jetbrains.php.lang.psi.resolve.types.PhpType;
import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider3;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.Set;

/**
* $this->prophesize(Foobar::class)->find()->will<caret>Return;
*
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class ProphecyTypeProvider implements PhpTypeProvider3 {
@Override
public char getKey() {
return '\u1530';
}

@Nullable
@Override
public PhpType getType(PsiElement element) {
if(element instanceof MethodReference) {
PhpExpression classReference = ((MethodReference) element).getClassReference();
if(classReference instanceof Variable || classReference instanceof MethodReference) {
Method method = PhpPsiUtil.getParentByCondition(element, Method.INSTANCEOF);
if(method != null) {
PhpClass containingClass = method.getContainingClass();

// filter phpunit test methods
if(containingClass != null && containingClass.getName().endsWith("Test")) {
boolean isProphesize = classReference.getType().getTypes().stream().anyMatch(s -> {
boolean b = s.startsWith("#" + MockProphecyTypeProvider.CHAR);
if (!b) {
return false;
}

int i = s.indexOf(MockProphecyTypeProvider.TRIM_KEY);
return i >= 0 && s.substring(2, i).endsWith("prophesize");
});

if(isProphesize) {
return (new PhpType()).add("\\Prophecy\\Prophecy\\MethodProphecy");
}
}
}
}
}

return null;
}

@Override
public Collection<? extends PhpNamedElement> getBySignature(String expression, Set<String> visited, int depth, Project project) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package de.espend.idea.php.phpunit.tests.type;

import com.intellij.patterns.PlatformPatterns;
import com.jetbrains.php.lang.PhpFileType;
import com.jetbrains.php.lang.psi.elements.Method;
import de.espend.idea.php.phpunit.tests.PhpUnitLightCodeInsightFixtureTestCase;

import java.io.File;

/**
* @author Daniel Espendiller <daniel@espendiller.net>
* @see de.espend.idea.php.phpunit.type.ProphecyTypeProvider
*/
public class ProphecyTypeProviderTest extends PhpUnitLightCodeInsightFixtureTestCase {
public void setUp() throws Exception {
super.setUp();
myFixture.copyFileToProject("ProphecyTypeProvider.php");
}

public String getTestDataPath() {
return new File(this.getClass().getResource("fixtures").getFile()).getAbsolutePath();
}

public void testThatProphesizeForVariableIsResolved() {
assertPhpReferenceResolveTo(PhpFileType.INSTANCE, "<?php\n" +
"class FooTest extends \\PHPUnit\\Framework\\TestCase\n" +
" {\n" +
" public function testFoobar()\n" +
" {\n" +
" $foo = $this->prophesize(Foo::class);\n" +
" $foo->find()->will<caret>Return();\n" +
" }\n" +
" }",
PlatformPatterns.psiElement(Method.class).withName("willReturn")
);
}

public void testThatProphesizeForMethodReferenceIsResolved() {
assertPhpReferenceResolveTo(PhpFileType.INSTANCE, "<?php\n" +
"class FooTest extends \\PHPUnit\\Framework\\TestCase\n" +
" {\n" +
" public function testFoobar()\n" +
" {\n" +
" $foo = $this->prophesize(Foo::class)->find()->will<caret>Return();\n" +
" }\n" +
" }",
PlatformPatterns.psiElement(Method.class).withName("willReturn")
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace PHPUnit\Framework
{

use Prophecy\Prophecy\ObjectProphecy;

class TestCase extends \PHPUnit_Framework_MockObject_InvocationMocker
{
/**
* @param null $classOrInterface
* @return \Prophecy\Prophecy\ObjectProphecy
*/
protected function prophesize($classOrInterface = null)
{
return new ObjectProphecy();
}
};
}

namespace Prophecy\Prophecy
{
class ObjectProphecy
{
public function willExtend($class)
{
}
}

class MethodProphecy
{
public function willReturn()
{
}
}
}

namespace
{
class PHPUnit_Framework_MockObject_InvocationMocker
{
public function willReturn($value, ...$nextValues)
{
}
}

class Foo
{
public function getBar()
{
}
}
}

0 comments on commit d4219cb

Please sign in to comment.