Skip to content

Commit

Permalink
add references for Doctrine @Orm\Embedded.class Haehnchen#68
Browse files Browse the repository at this point in the history
  • Loading branch information
Haehnchen committed Sep 4, 2016
1 parent 8d40894 commit 5875765
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 5 deletions.
3 changes: 3 additions & 0 deletions META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,9 @@
<PhpAnnotationReferenceProvider implementation="de.espend.idea.php.annotation.doctrine.reference.DoctrineAnnotationTypeProvider"/>
<PhpAnnotationReferenceProvider implementation="de.espend.idea.php.annotation.doctrine.reference.DoctrineAnnotationFieldTypeProvider"/>
<PhpAnnotationDocTagAnnotator implementation="de.espend.idea.php.annotation.doctrine.annotator.RepositoryClassAnnotationAnnotator"/>

<PhpAnnotationReferenceProvider implementation="de.espend.idea.php.annotation.doctrine.reference.EmbeddedClassCompletionProvider"/>
<PhpAnnotationCompletionProvider implementation="de.espend.idea.php.annotation.doctrine.reference.EmbeddedClassCompletionProvider"/>
</extensions>

<extensions defaultExtensionNs="de.espend.idea.php.toolbox.extension">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package de.espend.idea.php.annotation.doctrine.reference;

import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.jetbrains.php.PhpIndex;
import com.jetbrains.php.completion.PhpCompletionUtil;
import com.jetbrains.php.lang.PhpLangUtil;
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
import de.espend.idea.php.annotation.extension.PhpAnnotationCompletionProvider;
import de.espend.idea.php.annotation.extension.PhpAnnotationReferenceProvider;
import de.espend.idea.php.annotation.extension.parameter.AnnotationCompletionProviderParameter;
import de.espend.idea.php.annotation.extension.parameter.AnnotationPropertyParameter;
import de.espend.idea.php.annotation.extension.parameter.PhpAnnotationReferenceProviderParameter;
import de.espend.idea.php.annotation.reference.references.PhpClassReference;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.Nullable;

/**
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class EmbeddedClassCompletionProvider implements PhpAnnotationReferenceProvider, PhpAnnotationCompletionProvider {
@Nullable
@Override
public PsiReference[] getPropertyReferences(AnnotationPropertyParameter parameter, PhpAnnotationReferenceProviderParameter referencesByElementParameter) {
if(parameter.getType() != AnnotationPropertyParameter.Type.PROPERTY_VALUE ||
!"class".equals(parameter.getPropertyName()) ||
!PhpLangUtil.equalsClassNames(parameter.getPhpClass().getPresentableFQN(), "Doctrine\\ORM\\Mapping\\Embedded")
) {
return new PsiReference[0];
}

PsiElement element = parameter.getElement();
if(!(element instanceof StringLiteralExpression) || StringUtils.isBlank(((StringLiteralExpression) element).getContents())) {
return new PsiReference[0];
}

return new PsiReference[] {
new PhpClassReference((StringLiteralExpression) element)
};
}

@Override
public void getPropertyValueCompletions(AnnotationPropertyParameter parameter, AnnotationCompletionProviderParameter completionParameter) {
if(parameter.getType() != AnnotationPropertyParameter.Type.PROPERTY_VALUE ||
!"class".equals(parameter.getPropertyName()) ||
!PhpLangUtil.equalsClassNames(parameter.getPhpClass().getPresentableFQN(), "Doctrine\\ORM\\Mapping\\Embedded")
) {
return;
}

String className = "";
PsiElement element = parameter.getElement();
if(element instanceof StringLiteralExpression) {
className = ((StringLiteralExpression) element).getContents();
}

PhpIndex phpIndex = PhpIndex.getInstance(parameter.getProject());
PhpCompletionUtil.addClasses(className, completionParameter.getResult(), phpIndex, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiRecursiveElementVisitor;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
Expand All @@ -43,7 +40,6 @@
import com.jetbrains.php.lang.psi.elements.Function;
import com.jetbrains.php.lang.psi.elements.Method;
import com.jetbrains.php.lang.psi.elements.PhpReference;
import de.espend.idea.php.annotation.Settings;
import org.jetbrains.annotations.NotNull;

import java.io.File;
Expand Down Expand Up @@ -322,6 +318,52 @@ public void assertPhpReferenceSignatureEquals(LanguageFileType languageFileType,
assertEquals(typeSignature, ((PhpReference) psiElement).getSignature());
}

public void assertReferenceMatchOnParent(@NotNull FileType fileType, @NotNull String contents, @NotNull ElementPattern<?> pattern) {
myFixture.configureByText(fileType, contents);
PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
if(psiElement == null) {
fail("Fail to find element in caret");
}

PsiElement parent = psiElement.getParent();
if(parent == null) {
fail("Fail to find parent element in caret");
}

assertReferences(pattern, parent);
}

public void assertReferenceMatch(@NotNull FileType fileType, @NotNull String contents, @NotNull ElementPattern<?> pattern) {
myFixture.configureByText(fileType, contents);
PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
if(psiElement == null) {
fail("Fail to find element in caret");
}

assertReferences(pattern, psiElement);
}

private void assertReferences(@NotNull ElementPattern<?> pattern, PsiElement psiElement) {
for (PsiReference reference : psiElement.getReferences()) {
// single resolve; should also match first multi by design
PsiElement element = reference.resolve();
if (pattern.accepts(element)) {
return;
}

// multiResolve support
if(element instanceof PsiPolyVariantReference) {
for (ResolveResult resolveResult : ((PsiPolyVariantReference) element).multiResolve(true)) {
if (pattern.accepts(resolveResult.getElement())) {
return;
}
}
}
}

fail(String.format("Fail that '%s' match given pattern", psiElement.toString()));
}

public void assertCompletionResultEquals(String filename, String complete, String result) {
myFixture.configureByText(filename, complete);
myFixture.completeBasic();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package de.espend.idea.php.annotation.tests.doctrine.reference;

import com.intellij.patterns.PlatformPatterns;
import com.jetbrains.php.lang.PhpFileType;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import de.espend.idea.php.annotation.tests.AnnotationLightCodeInsightFixtureTestCase;

import java.io.File;

/**
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class EmbeddedClassCompletionProviderTest extends AnnotationLightCodeInsightFixtureTestCase {
public void setUp() throws Exception {
super.setUp();
myFixture.copyFileToProject("classes.php");
}

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

public void testThatDoctrineEmbeddedClassPropertyProvidesClassReferences() {
assertCompletionContains(PhpFileType.INSTANCE, "<?php\n" +
"use Doctrine\\ORM\\Mapping as ORM;\n" +
"class Foo\n" +
"{\n" +
" /** @ORM\\Embedded(class=\"<caret>\") */\n" +
" protected $logo;\n" +
"}",
"Bar"
);

assertReferenceMatchOnParent(PhpFileType.INSTANCE, "<?php\n" +
"use Doctrine\\ORM\\Mapping as ORM;\n" +
"class Foo\n" +
"{\n" +
" /** @ORM\\Embedded(class=\"My\\FooC<caret>lass\\Bar\") */\n" +
" protected $logo;\n" +
"}",
PlatformPatterns.psiElement(PhpClass.class)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Doctrine\ORM\Mapping
{
/**
* @Annotation
* @Target("PROPERTY")
*/
final class Embedded implements Annotation
{
}
}

namespace My\FooClass
{
class Bar
{
}
}

0 comments on commit 5875765

Please sign in to comment.