Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
import fr.adrienbrault.idea.symfony2plugin.doctrine.querybuilder.dict.QueryBuilderPropertyAlias;
import fr.adrienbrault.idea.symfony2plugin.doctrine.querybuilder.dict.QueryBuilderRelation;
import fr.adrienbrault.idea.symfony2plugin.doctrine.querybuilder.util.MatcherUtil;
import fr.adrienbrault.idea.symfony2plugin.doctrine.querybuilder.util.QueryBuilderUtil;
import fr.adrienbrault.idea.symfony2plugin.util.MethodMatcher;
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
Expand All @@ -27,26 +29,56 @@ public class QueryBuilderGotoDeclarationHandler implements GotoDeclarationHandle

@Nullable
@Override
public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int i, Editor editor) {
public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int offset, Editor editor) {

if (!Symfony2ProjectComponent.isEnabled(psiElement) || !(psiElement.getContext() instanceof StringLiteralExpression)) {
return new PsiElement[0];
}

List<PsiElement> psiElements = new ArrayList<>();

attachPropertyGoto((StringLiteralExpression) psiElement.getContext(), psiElements);
attachJoinGoto((StringLiteralExpression) psiElement.getContext(), psiElements);
StringLiteralExpression context = (StringLiteralExpression) psiElement.getContext();
attachPropertyGoto(context, psiElements);
attachJoinGoto(context, psiElements);
attachPartialGoto(context, psiElements, offset);

// $qb->expr()->in('')
attachExprGoto((StringLiteralExpression) psiElement.getContext(), psiElements);
attachExprGoto(context, psiElements);

// $qb->from('', '', '<foo>');
attachFromIndexGoto((StringLiteralExpression) psiElement.getContext(), psiElements);
attachFromIndexGoto(context, psiElements);

return psiElements.toArray(new PsiElement[psiElements.size()]);
}

private void attachPartialGoto(@NotNull StringLiteralExpression psiElement, @NotNull List<PsiElement> targets, int offset) {
MethodMatcher.MethodMatchParameter methodMatchParameter = MatcherUtil.matchWhere(psiElement);
if(methodMatchParameter == null) {
return;
}

int calulatedOffset = offset - psiElement.getTextRange().getStartOffset();
if (calulatedOffset < 0) {
calulatedOffset = 0;
}

String contents = psiElement.getContents();
String fieldString = QueryBuilderUtil.getFieldString(contents, calulatedOffset);
if (fieldString != null) {
QueryBuilderMethodReferenceParser qb = QueryBuilderCompletionContributor.getQueryBuilderParser(methodMatchParameter.getMethodReference());
if(qb == null) {
return;
}

QueryBuilderScopeContext collect = qb.collect();
for(Map.Entry<String, QueryBuilderPropertyAlias> entry: collect.getPropertyAliasMap().entrySet()) {
if(entry.getKey().equals(fieldString)) {
targets.addAll(entry.getValue().getPsiTargets());
}
}
}
}

private void attachJoinGoto(StringLiteralExpression psiElement, List<PsiElement> targets) {

MethodMatcher.MethodMatchParameter methodMatchParameter = MatcherUtil.matchJoin(psiElement);
Expand Down Expand Up @@ -76,11 +108,8 @@ private void attachJoinGoto(StringLiteralExpression psiElement, List<PsiElement>
if(phpClass != null) {
targets.add(phpClass);
}

}
}


}

private void attachPropertyGoto(StringLiteralExpression psiElement, List<PsiElement> targets) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,12 @@ public static MethodMatcher.MethodMatchParameter matchJoin(PsiElement psiElement
}



@Nullable
public static MethodMatcher.MethodMatchParameter matchWhere(PsiElement psiElement) {
return new MethodMatcher.StringParameterMatcher(psiElement, 0)
.withSignature("\\Doctrine\\ORM\\QueryBuilder", "andWhere")
.withSignature("\\Doctrine\\ORM\\QueryBuilder", "where")
.withSignature("\\Doctrine\\ORM\\QueryBuilder", "orWhere")
.match();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectRepositoryTypeProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.HashSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* @author Daniel Espendiller <daniel@espendiller.net>
Expand Down Expand Up @@ -32,4 +35,35 @@ public static Collection<String> extractQueryBuilderRepositoryParameters(@NotNul

return results;
}

/**
* test "test.fooTe<caret>aa = aa"
*/
@Nullable
public static String getFieldString(@NotNull String content, int offset) {
if (offset > content.length()) {
return null;
}

String substring1 = content.substring(0, offset);
Matcher matcherBefore = Pattern.compile("([\\w.]+)[\\s|>=<]?$").matcher(substring1);
if (!matcherBefore.find()) {
return null;
}

String substring = content.substring(offset);
Matcher matcherAfter = Pattern.compile("^[\\s|>=<]?([\\w.]+)").matcher(substring);
if (!matcherAfter.find()) {
return null;
}

String field = matcherBefore.group(1) + matcherAfter.group(1);

// invalid field
if (!field.contains(".")) {
return null;
}

return field;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package fr.adrienbrault.idea.symfony2plugin.tests.doctrine.querybuilder.util;

import com.intellij.openapi.util.Pair;
import fr.adrienbrault.idea.symfony2plugin.doctrine.querybuilder.util.QueryBuilderUtil;
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;

import java.util.ArrayList;
import java.util.Collection;

/**
Expand All @@ -25,4 +27,26 @@ public void testExtractQueryBuilderRepositoryParametersForClassConstant() {

assertContainsElements(strings, "#K#C\\espend\\Doctrine\\ModelBundle\\Entity\\Car.class");
}

public void testGetFieldString() {
Collection<Pair<String, String>> items = new ArrayList<>() {{
add(Pair.create("user.foo = :foo AND user.ba<caret>r AND bar.foo", "user.bar"));
add(Pair.create("user.foo = :foo AND us<caret>er.bar AND bar.foo", "user.bar"));
add(Pair.create("user.ba<caret>r>=", "user.bar"));
add(Pair.create(">=user.ba<caret>r", "user.bar"));
add(Pair.create("user.<caret>bar", "user.bar"));
add(Pair.create("user<caret>.bar", "user.bar"));
add(Pair.create("user.ba<caret>rÄ", "user.bar")); // nice usability but should this really match?
add(Pair.create("us<caret>er.barÄ", "user.bar")); // nice usability but should this really match?
add(Pair.create("us<caret>er", null));
// add(Pair.create("user.bar<caret> AND", null)); // ???
}};

for (Pair<String, String> item : items) {
String content = item.getFirst();

String string = QueryBuilderUtil.getFieldString(content.replace("<caret>", ""), content.indexOf("<caret>"));
assertEquals(item.getSecond(), string);
}
}
}