package sk.sorien.pimpleplugin.tests.pimple; import com.intellij.openapi.project.Project; import com.jetbrains.php.lang.PhpFileType; import com.jetbrains.php.lang.psi.elements.*; import org.jetbrains.annotations.NotNull; import sk.sorien.pimpleplugin.pimple.*; import sk.sorien.pimpleplugin.pimple.Parameter; import sk.sorien.pimpleplugin.tests.CodeInsightFixtureTestCase; import java.io.File; /** * @author Stanislav Turza */ public class PimplePhpTypeProviderTest extends CodeInsightFixtureTestCase { @Override public void setUp() throws Exception { super.setUp(); Project project = myFixture.getProject(); // Create virtual container Container container = new Container(project); container.put(new Container("container1", project).put(new Container("container2", project).put(new Service("service1", "\\Sorien\\Service1")))); container.put(new Parameter("service2_class", ParameterType.STRING, "\\Sorien\\Service2")); container.put(new Service("service2", "\\Sorien\\Service2")); container.put(new Service("Sorien\\Service2", "\\Sorien\\Service2")); ContainerResolver.put(myFixture.getProject(), container); // Add Fixtures myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject("classes.php")); } @Override public void tearDown() throws Exception { ContainerResolver.remove(myFixture.getProject()); super.tearDown(); } @NotNull protected String getTestDataPath() { return new File(this.getClass().getResource("fixtures").getFile()).getAbsolutePath(); } public void testTypeForArrayAccessContainer() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, ArrayAccessExpression.class, "<?php " + "$app = new \\Silex\\Application(); " + "$a<caret>pp['service1'];", "#Š#C\\Silex\\Application[service1]" ); } public void testTypeForArrayAccessMultiContainer() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, ArrayAccessExpression.class, "<?php " + "$app = new \\Silex\\Application(); " + "$app['service1']['ser<caret>vice2'];", "#Š#C\\Silex\\Application[service1][service2]" ); } public void testTypeForArrayAccessContainerConstantKey() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, ArrayAccessExpression.class, "<?php " + "class Test {" + " const c = \"container1\";" + "}" + "$app = new \\Silex\\Application();" + "$app[Test::c]['service1<caret>']", "#Š#C\\Silex\\Application[#K#C\\Test.c][service1]" ); } public void testTypeForArrayAccessContainerPropertyKey() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, ArrayAccessExpression.class, "<?php " + "class Test {" + " public $property = \"container1\";" + "}" + "$app = new \\Silex\\Application();" + "$class = new Test();" + "$app[$class->property]['service1<caret>']", "#Š#C\\Silex\\Application[#P#C\\Test.property][service1]" ); } public void testTypeForArrayAccessReferencedContainer() throws Exception { assertTypeEquals(PhpFileType.INSTANCE, Variable.class, "<?php " + "$app = new \\Silex\\Application(); " + "$a = $app['container1']; " + "$b = $a['container2']; " + "$se<caret>rvice = $b['service1']", "\\Sorien\\Service1" ); } public void testTypeForArrayNewExpressionSignature() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, NewExpression.class, "<?php " + "$app = new \\Silex\\Application(); " + "$abc = new $a<caret>pp['service2_class']();", "#Š#C\\Silex\\Application[@service2_class]" ); } public void testTypeForParameterFactoryMethod() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application(); " + "$app[''] = $app->factory(function ($<caret>class) {});", "#Š#C\\Silex\\Application" ); } public void testTypeForParameterShareMethod() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application(); " + "$app[''] = $app->share(function ($<caret>class) {});", "#Š#C\\Silex\\Application" ); } public void testTypeForTypedParameterShareMethod() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application(); " + "$app[''] = $app->share(function (MyPimpleType $<caret>class) {});", null ); } public void testTypeForParameterAnonymousFunction() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application(); " + "$app['service2'] = function ($<caret>app) {};", "#Š#C\\Silex\\Application" ); } public void testTypeForParameterExtendMethodOneParameter() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application(); " + "$app[''] = $app->extend('service2', function ($<caret>class) {});", "#Š#C\\Silex\\Application[service2]" ); } public void testTypeForTypedParameterExtendMethodOneParameter() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application(); " + "$app[''] = $app->extend('service2', function (MyPimpleType $<caret>class) {});", null ); } public void testTypeForParameterExtendMethodTwoParameters() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application(); " + "$app[''] = $app->extend('service2', function ($class, $a<caret>pplication) {});", "#Š#C\\Silex\\Application" ); } public void testTypeForTypedParameterExtendMethodTwoParameters() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application(); " + "$app[''] = $app->extend('service2', function ($class, MyPimpleType $a<caret>pplication) {});", null ); } public void testTypeForParameterExtendMethodSubContainer() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application(); " + "$app['container1']['container2']->extend('service1', function ($<caret>class) {});", "#Š#C\\Silex\\Application[container1][container2][service1]" ); } public void testTypeForParameterConstKey() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application();" + "$app['container1']['container2']->extend(\\Sorien\\Service1::name, function ($<caret>class) {});", "#Š#C\\Silex\\Application[container1][container2][#K#C\\Sorien\\Service1.name]" ); } public void testTypeForParameterPropertyKey() throws Exception { assertSignatureEquals(PhpFileType.INSTANCE, com.jetbrains.php.lang.psi.elements.Parameter.class, "<?php " + "$app = new \\Silex\\Application();" + "$service2 = new \\Sorien\\Service2();" + "$app->extend($service2->name, function ($<caret>class) {});", "#Š#C\\Silex\\Application[#P#C\\Sorien\\Service2.name]" ); } public void ProperArrayValueTypeIfServiceCantBeResolved() throws Exception { assertTypeEquals(PhpFileType.INSTANCE, Variable.class, "<?php " + "class Publication {};" + "class Foo {" + " /** @var Publication[] */" + " public $publications;" + " public function collect() {" + " $var<caret>a = $this->publications['test'];" + " }" + "};", "\\Publication" ); } public void testResolvedTypeForQuotedFqnServiceName() throws Exception { assertTypeEquals(PhpFileType.INSTANCE, Variable.class, "<?php " + "$app = new \\Silex\\Application();" + "$<caret>a = $app[\"Sorien\\\\Service2\"];", "\\Sorien\\Service2" ); } public void testResolvedTypeForServiceNameBasedOnClassClass() throws Exception { assertTypeEquals(PhpFileType.INSTANCE, Variable.class, "<?php " + "$app = new \\Silex\\Application();" + "$<caret>a = $app[\\Sorien\\Service2::class\"];", "\\Sorien\\Service2" ); } public void testDoNotResolveArrayOfSimpleType() throws Exception { String fixture = "<?php " + "/** @var %type[] $array */" + "$array = [1, 2, 3];" + "$index = 0;" + "$<caret>foo = $array[$index];"; assertSignatureEquals(PhpFileType.INSTANCE, Variable.class, fixture.replace("%type", "array"), null); assertSignatureEquals(PhpFileType.INSTANCE, Variable.class, fixture.replace("%type", "int"), null); assertSignatureEquals(PhpFileType.INSTANCE, Variable.class, fixture.replace("%type", "integer"), null); assertSignatureEquals(PhpFileType.INSTANCE, Variable.class, fixture.replace("%type", "string"), null); assertSignatureEquals(PhpFileType.INSTANCE, Variable.class, fixture.replace("%type", "float"), null); assertSignatureEquals(PhpFileType.INSTANCE, Variable.class, fixture.replace("%type", "bool"), null); assertSignatureEquals(PhpFileType.INSTANCE, Variable.class, fixture.replace("%type", "boolean"), null); } public void testResolveSignatureToPhpClass() throws Exception { assertSignatureEqualsType("#C\\Silex\\Application[Sorien\\Service2]", "\\Sorien\\Service2"); assertSignatureEqualsType("#C\\Silex\\Application[@service2_class]", "\\Sorien\\Service2"); //assertSignatureEqualsType("#Š#Š#C\\Silex\\Application[container1][container2][service1]", "\\Sorien\\Service1"); //assertSignatureEqualsType("#Š#Š#C\\Silex\\Application[container1][container2][#K#C\\Sorien\\Service1.name]", "\\Sorien\\Service1"); assertSignatureEqualsType("#C\\Silex\\Application[#P#C\\Sorien\\Service2.name]", "\\Sorien\\Service2"); assertSignatureEqualsType("#C\\Silex\\Application[#K#C\\Sorien\\Service2.class]", "\\Sorien\\Service2"); } public void testSignature() throws Exception { assertEquals("#C\\Silex\\Application", new Signature("#C\\Silex\\Application[#P#C\\Sorien\\Service2.name]").base); assertEquals("#P#C\\Sorien\\Service2.name", new Signature("#C\\Silex\\Application[#P#C\\Sorien\\Service2.name]").parameter); assertEquals("#C\\Silex\\Application", new Signature("#C\\Silex\\Application[#C\\Pimple[@service2_class]]").base); assertEquals("#C\\Pimple[@service2_class]", new Signature("#C\\Silex\\Application[#C\\Pimple[@service2_class]]").parameter); } }