Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #197 from zulus/ca_improvement

Improve code assist
  • Loading branch information...
commit 262a492e02464c36df012a26bff9ebbf468bfe1c 2 parents c59f69a + c84aec4
@pulse00 authored
Showing with 475 additions and 201 deletions.
  1. +73 −22 com.dubture.symfony.core/src/com/dubture/symfony/core/codeassist/contexts/ServiceReturnTypeContext.java
  2. +26 −25 ...re.symfony.core/src/com/dubture/symfony/core/codeassist/strategies/ServiceReturnTypeCompletionStrategy.java
  3. +25 −47 com.dubture.symfony.core/src/com/dubture/symfony/core/goals/ContainerAwareGoalEvaluatorFactory.java
  4. +47 −0 com.dubture.symfony.core/src/com/dubture/symfony/core/goals/ServiceTypeGoal.java
  5. +112 −20 com.dubture.symfony.core/src/com/dubture/symfony/core/goals/evaluator/ServiceGoalEvaluator.java
  6. +53 −0 com.dubture.symfony.core/src/com/dubture/symfony/core/goals/evaluator/ServiceTypeGoalEvaluator.java
  7. +5 −1 com.dubture.symfony.core/src/com/dubture/symfony/core/preferences/SymfonyCoreConstants.java
  8. +103 −79 com.dubture.symfony.core/src/com/dubture/symfony/core/util/text/SymfonyTextSequenceUtilities.java
  9. +4 −0 com.dubture.symfony.test/workspace/services/ContainerInterface.php
  10. +6 −0 com.dubture.symfony.test/workspace/services/Controller.php
  11. +1 −1  com.dubture.symfony.test/workspace/services/testChainedServiceCompletion.pdtt
  12. +1 −1  com.dubture.symfony.test/workspace/services/testParameterizedServiceMethodCompletion.pdtt
  13. +1 −1  com.dubture.symfony.test/workspace/services/testServiceIdCompletion.pdtt
  14. +3 −2 com.dubture.symfony.test/workspace/services/testServiceMethodCompletion.pdtt
  15. +14 −0 com.dubture.symfony.test/workspace/services/testServiceMethodCompletion2.pdtt
  16. +1 −2  com.dubture.symfony.ui/src/com/dubture/symfony/ui/contentassist/SymfonyCompletionProposalCollector.java
View
95 ...mfony.core/src/com/dubture/symfony/core/codeassist/contexts/ServiceReturnTypeContext.java
@@ -1,8 +1,8 @@
/*******************************************************************************
* This file is part of the Symfony eclipse plugin.
- *
+ *
* (c) Robert Gruendler <r.gruendler@gmail.com>
- *
+ *
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
******************************************************************************/
@@ -12,27 +12,34 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.dltk.core.CompletionRequestor;
import org.eclipse.dltk.core.ISourceModule;
+import org.eclipse.dltk.core.IType;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.php.internal.core.codeassist.CodeAssistUtils;
import org.eclipse.php.internal.core.codeassist.contexts.ClassMemberContext;
+import org.eclipse.php.internal.core.format.PHPHeuristicScanner;
+import org.eclipse.php.internal.core.typeinference.PHPModelUtils;
+import org.eclipse.php.internal.core.util.text.PHPTextSequenceUtilities;
+import org.eclipse.php.internal.core.util.text.TextSequence;
import com.dubture.symfony.core.builder.SymfonyNature;
import com.dubture.symfony.core.log.Logger;
+import com.dubture.symfony.core.preferences.SymfonyCoreConstants;
import com.dubture.symfony.core.util.text.SymfonyTextSequenceUtilities;
-
/**
- *
+ *
* A context which is valid when completing services directly from
* the DI container:
- *
- *
+ *
+ *
* <pre>
- *
+ *
* $em = $this->get('doctrine')-> |
- *
+ *
* </pre>
- *
- *
- *
+ *
+ *
+ *
* @author Robert Gruendler <r.gruendler@gmail.com>
*
*/
@@ -44,26 +51,70 @@
public boolean isValid(ISourceModule sourceModule, int offset,
CompletionRequestor requestor) {
- if (super.isValid(sourceModule, offset, requestor))
- {
-
+ if (super.isValid(sourceModule, offset, requestor))
+ {
+
try {
-
- IProjectNature nature;
+ IProjectNature nature;
nature = sourceModule.getScriptProject().getProject().getNature(SymfonyNature.NATURE_ID);
-
+
// wrong nature
if(!(nature instanceof SymfonyNature)) {
- return false;
+ return false;
+ }
+ // Check function name
+ if (SymfonyTextSequenceUtilities.isGetFunction(getStatementText()) == -1) {
+ return false;
+ }
+
+ TextSequence statementText = getStatementText();
+ int totalLength = statementText.length();
+ int elementStart = PHPTextSequenceUtilities.readBackwardSpaces(
+ statementText, totalLength);
+ elementStart = PHPTextSequenceUtilities.readIdentifierStartIndex(
+ statementText, elementStart, true);
+ elementStart = PHPTextSequenceUtilities.readBackwardSpaces(
+ statementText, elementStart);
+ elementStart-=3;
+ if (statementText.charAt(elementStart) != ')') { //
+ return false;
+ }
+
+ // find get()
+ PHPHeuristicScanner scanner = PHPHeuristicScanner.createHeuristicScanner(getDocument(), offset - statementText.length() + elementStart-1, true);
+ int open = scanner.findOpeningPeer(offset - statementText.length() + elementStart-1, PHPHeuristicScanner.UNBOUND, PHPHeuristicScanner.LPAREN, PHPHeuristicScanner.RPAREN);
+ statementText = getStatementText(open);
+ totalLength = statementText.length();
+ elementStart = PHPTextSequenceUtilities.readBackwardSpaces(
+ statementText, totalLength);
+ elementStart = PHPTextSequenceUtilities.readIdentifierStartIndex(
+ statementText, elementStart, true);
+
+
+ // read lhs types
+ IType[] lhsTypes = CodeAssistUtils.getTypesFor(getSourceModule(), statementText, elementStart, open);
+
+ for (IType type : lhsTypes) {
+ if (type.getFullyQualifiedName("\\").equals(SymfonyCoreConstants.CONTAINER_INTERFACE) || type.getFullyQualifiedName("\\").equals(SymfonyCoreConstants.CONTROLLER_PARENT)) {
+ return true;
+ }
+
+ IType[] superClasses = PHPModelUtils.getSuperClasses(type, getCompanion().getSuperTypeHierarchy(type, null));
+ for (IType sc : superClasses) {
+ if (sc.getFullyQualifiedName("\\").equals(SymfonyCoreConstants.CONTAINER_INTERFACE) || sc.getFullyQualifiedName("\\").equals(SymfonyCoreConstants.CONTROLLER_PARENT)) {
+ return true;
+ }
+ }
}
-
- return SymfonyTextSequenceUtilities.isInServiceContainerFunction(getStatementText()) > -1;
-
+
} catch (CoreException e) {
Logger.logException(e);
+ } catch (BadLocationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
}
}
-
+
return false;
}
}
View
51 ...c/com/dubture/symfony/core/codeassist/strategies/ServiceReturnTypeCompletionStrategy.java
@@ -1,8 +1,8 @@
/*******************************************************************************
* This file is part of the Symfony eclipse plugin.
- *
+ *
* (c) Robert Gruendler <r.gruendler@gmail.com>
- *
+ *
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
******************************************************************************/
@@ -20,11 +20,13 @@
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.internal.core.SourceRange;
import org.eclipse.php.core.codeassist.ICompletionContext;
+import org.eclipse.php.core.compiler.PHPFlags;
import org.eclipse.php.internal.core.codeassist.CodeAssistUtils;
import org.eclipse.php.internal.core.codeassist.ICompletionReporter;
import org.eclipse.php.internal.core.codeassist.contexts.AbstractCompletionContext;
import org.eclipse.php.internal.core.codeassist.strategies.ClassMembersStrategy;
import org.eclipse.php.internal.core.model.PhpModelAccess;
+import org.eclipse.php.internal.core.typeinference.PHPModelUtils;
import com.dubture.symfony.core.codeassist.contexts.ServiceReturnTypeContext;
import com.dubture.symfony.core.model.Service;
@@ -32,14 +34,14 @@
import com.dubture.symfony.core.util.text.SymfonyTextSequenceUtilities;
/**
- *
+ *
* A completionstrategy that reports methods from a service returned
* by the DI container.
- *
- *
+ *
+ *
* @see ServiceReturnTypeContext
- *
- *
+ *
+ *
* @author Robert Gruendler <r.gruendler@gmail.com>
*
*/
@@ -51,7 +53,6 @@
public ServiceReturnTypeCompletionStrategy(ICompletionContext context) {
super(context);
-
}
@Override
@@ -60,10 +61,10 @@ public void apply(ICompletionReporter reporter) throws Exception {
ServiceReturnTypeContext context = (ServiceReturnTypeContext) getContext();
IScriptProject project = context.getSourceModule().getScriptProject();
String source = SymfonyTextSequenceUtilities.getServiceFromMethodParam(context.getStatementText());
-
+
if (source == null)
return;
-
+
Service service = SymfonyModelAccess.getDefault().findService(source, project.getPath());
if (service == null) {
return;
@@ -74,33 +75,33 @@ public void apply(ICompletionReporter reporter) throws Exception {
// if that's possible.
//
// this way, we could avoid the SearchEngine call here
-
+
String namespace = service.getSimpleNamespace();
IType[] types = getTypes(context, service.getClassName(), namespace);
-
+
if (types.length != 1) {
return;
}
-
- IType type = types[0];
- SourceRange range = getReplacementRange(context);
+
+ IType type = types[0];
+ SourceRange range = getReplacementRange(context);
String prefix = context.getPrefix();
-
- for(IMethod method : type.getMethods()) {
- if (CodeAssistUtils.startsWithIgnoreCase(method.getElementName(), prefix)) {
- reporter.reportMethod(method, "", range);
- }
+
+ for(IMethod method : type.getMethods()) {
+ if (!PHPModelUtils.isConstructor(method) && PHPFlags.isPublic(method.getFlags()) && CodeAssistUtils.startsWithIgnoreCase(method.getElementName(), prefix)) {
+ reporter.reportMethod(method, "", range);
+ }
}
}
-
+
private IType[] getTypes(AbstractCompletionContext context, String prefix, String pkg) {
-
+
IDLTKSearchScope scope = createSearchScope();
List<IType> result = new LinkedList<IType>();
IType[] types = PhpModelAccess.getDefault().findTypes(pkg, prefix,
MatchRule.EXACT, trueFlag, falseFlag, scope, null);
result.addAll(Arrays.asList(types));
-
- return (IType[]) result.toArray(new IType[result.size()]);
- }
+
+ return (IType[]) result.toArray(new IType[result.size()]);
+ }
}
View
72 ...e.symfony.core/src/com/dubture/symfony/core/goals/ContainerAwareGoalEvaluatorFactory.java
@@ -10,20 +10,22 @@
import java.util.List;
+import org.eclipse.core.resources.IProjectNature;
import org.eclipse.dltk.ast.ASTNode;
-import org.eclipse.dltk.ast.references.VariableReference;
import org.eclipse.dltk.ti.IGoalEvaluatorFactory;
+import org.eclipse.dltk.ti.ISourceModuleContext;
import org.eclipse.dltk.ti.goals.ExpressionTypeGoal;
import org.eclipse.dltk.ti.goals.GoalEvaluator;
import org.eclipse.dltk.ti.goals.IGoal;
import org.eclipse.php.internal.core.compiler.ast.nodes.PHPCallExpression;
import org.eclipse.php.internal.core.compiler.ast.nodes.Scalar;
+import org.eclipse.php.internal.core.compiler.ast.parser.ASTUtils;
import org.eclipse.php.internal.core.typeinference.context.MethodContext;
import org.eclipse.php.internal.core.typeinference.goals.phpdoc.PHPDocMethodReturnTypeGoal;
+import com.dubture.symfony.core.builder.SymfonyNature;
import com.dubture.symfony.core.goals.evaluator.ServiceGoalEvaluator;
-import com.dubture.symfony.core.model.Service;
-import com.dubture.symfony.core.model.SymfonyModelAccess;
+import com.dubture.symfony.core.goals.evaluator.ServiceTypeGoalEvaluator;
/**
@@ -52,13 +54,17 @@ public GoalEvaluator createEvaluator(IGoal goal) {
try {
this.goal = goal;
- //TODO: find a way to check project nature
- // and return null if it's not a symfonyNature
- // goal.getContext().getLangNature() always returns the PHPNature...
- GoalEvaluator evaluator = evaluateServiceCalls(goal);
-
+ if (goal.getContext() instanceof ISourceModuleContext) {
+ ISourceModuleContext context = (ISourceModuleContext) goal.getContext();
+ IProjectNature nature = context.getSourceModule().getScriptProject().getProject().getNature(SymfonyNature.NATURE_ID);
+ if(!(nature instanceof SymfonyNature)) {
+ return null;
+ }
+ } else {
+ return null;
+ }
//TODO: add more evaluators...
- return evaluator;
+ return evaluateServiceCalls(goal);
} catch (Exception e) {
return null;
@@ -91,49 +97,24 @@ private GoalEvaluator evaluateServiceCalls(IGoal goal) {
// MethodContext context = (MethodContext) goal.getContext();
// PHPClassType classType = (PHPClassType) context.getInstanceType();
-
if (goalClass == ExpressionTypeGoal.class) {
-
-
ExpressionTypeGoal expGoal = (ExpressionTypeGoal) goal;
ASTNode expression = expGoal.getExpression();
// we're inside a call expression in the form $em->|
if (expression instanceof PHPCallExpression) {
-
-
-
PHPCallExpression exp = (PHPCallExpression) expression;
- ASTNode receiver = exp.getReceiver();
-
// are we calling a method named "get" ?
- if (exp.getName().equals("get") && receiver instanceof VariableReference) {
-
- VariableReference ref = (VariableReference) receiver;
-
- // is the receiver an object instance ?
- if (ref.getName().equals("$this")) {
- return getEvaluator(exp);
- }
- } else if (exp.getName().equals("get") && receiver instanceof PHPCallExpression) {
-
- PHPCallExpression call = (PHPCallExpression) receiver;
-
- if (call.getName().equals("getContainer")) {
- return getEvaluator(exp);
- }
+ if (exp.getName().equals("get")) {
+ return getEvaluator(exp);
}
}
// we're checking a PHPDocMethodReturnTypeGoal like $em = $this->get('doctrine')->|
// to support fluent interfaces.
- } else if (goalClass == PHPDocMethodReturnTypeGoal.class) {
-
-// PHPDocMethodReturnTypeGoal mGoal = (PHPDocMethodReturnTypeGoal) goal;
-// if (mGoal.getMethodName().equals("get")) {
-// return new ContainerMethodReturnTypeEvaluator(mGoal);
-// }
+ } else if (goalClass == ServiceTypeGoal.class) {
+ return new ServiceTypeGoalEvaluator((ServiceTypeGoal)goal);
}
// Give the control to the default PHP goal evaluator
@@ -146,21 +127,18 @@ private ServiceGoalEvaluator getEvaluator(PHPCallExpression exp) {
List args = exp.getArgs().getChilds();
- // does the get() method have exact one argument?
- if (args.size() == 1) {
+ // does the get() method have minimum one argument?
+ if (args.size() >= 1) {
Object first = args.get(0);
-
+ // TODO resolve quotes
if (first instanceof Scalar && ((Scalar)first).getScalarType() == Scalar.TYPE_STRING) {
- //TODO: check if there are PDT utils for stripping away quotes from
- // string literals.
- String className = ((Scalar)first).getValue().replace("'", "").replace("\"", "");
- Service service = SymfonyModelAccess.getDefault().findService(className,context.getSourceModule().getScriptProject().getPath());
+ String serviceName = ASTUtils.stripQuotes(((Scalar)first).getValue());
// we got a service match, return the goalevaluator.
- if (service != null) {
- return new ServiceGoalEvaluator(goal, service);
+ if (serviceName != null) {
+ return new ServiceGoalEvaluator(goal, serviceName);
}
}
}
View
47 com.dubture.symfony.core/src/com/dubture/symfony/core/goals/ServiceTypeGoal.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * This file is part of the Symfony eclipse plugin.
+ *
+ * (c) Dawid Pakuła <zulus@w3des.net>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ ******************************************************************************/
+package com.dubture.symfony.core.goals;
+
+import org.eclipse.dltk.ti.IContext;
+import org.eclipse.dltk.ti.goals.AbstractGoal;
+
+public class ServiceTypeGoal extends AbstractGoal{
+
+
+ private final String serviceId;
+
+ public ServiceTypeGoal(IContext context, String serviceId) {
+ super(context);
+ assert serviceId != null;
+ this.serviceId = serviceId;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ } else if (!super.equals(obj)) {
+ return false;
+ } else if (this.getClass() != obj.getClass()) {
+ return false;
+ }
+
+ return serviceId.equals(((ServiceTypeGoal) obj).getServiceId());
+ }
+
+ @Override
+ public int hashCode() {
+ return 41 * super.hashCode() + serviceId.hashCode();
+ }
+
+ public String getServiceId() {
+ return serviceId;
+ }
+
+}
View
132 ...bture.symfony.core/src/com/dubture/symfony/core/goals/evaluator/ServiceGoalEvaluator.java
@@ -1,58 +1,150 @@
/*******************************************************************************
* This file is part of the Symfony eclipse plugin.
- *
+ *
* (c) Robert Gruendler <r.gruendler@gmail.com>
- *
+ *
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
******************************************************************************/
package com.dubture.symfony.core.goals.evaluator;
+import org.eclipse.dltk.ast.ASTNode;
+import org.eclipse.dltk.ast.expressions.CallExpression;
+import org.eclipse.dltk.core.ISourceModule;
+import org.eclipse.dltk.core.IType;
+import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.ti.GoalState;
+import org.eclipse.dltk.ti.ISourceModuleContext;
+import org.eclipse.dltk.ti.goals.ExpressionTypeGoal;
import org.eclipse.dltk.ti.goals.GoalEvaluator;
import org.eclipse.dltk.ti.goals.IGoal;
-import org.eclipse.php.internal.core.typeinference.PHPClassType;
+import org.eclipse.dltk.ti.types.IEvaluatedType;
+import org.eclipse.php.internal.core.typeinference.IModelAccessCache;
+import org.eclipse.php.internal.core.typeinference.PHPModelUtils;
+import org.eclipse.php.internal.core.typeinference.context.IModelCacheContext;
-import com.dubture.symfony.core.model.Service;
+import com.dubture.symfony.core.goals.ServiceTypeGoal;
+import com.dubture.symfony.core.log.Logger;
+import com.dubture.symfony.core.preferences.SymfonyCoreConstants;
/**
- *
- *
- *
- * @author Robert Gruendler <r.gruendler@gmail.com>
*
+ * @author Robert Gruendler <r.gruendler@gmail.com>
*/
@SuppressWarnings("restriction")
public class ServiceGoalEvaluator extends GoalEvaluator {
- private Service service;
-
+ private ISourceModule sourceModule;
+
+ private final static int STATE_INIT = 0;
+ private final static int STATE_WAITING_RECEIVER = 1;
+ private final static int STATE_GOT_RECEIVER = 2;
+ private final static int STATE_WAITING_SERVICE_TYPE = 3;
+ private final static int STATE_GOT_SERVICE_TYPE = 4;
+
+ private IEvaluatedType receiverType;
+ private IEvaluatedType result;
- public ServiceGoalEvaluator(IGoal goal, Service service) {
+ private int state = STATE_INIT;
+
+ private String serviceName;
+
+ public ServiceGoalEvaluator(IGoal goal, String serviceName) {
super(goal);
- this.service = service;
+ this.serviceName = serviceName;
+ if (goal.getContext() instanceof ISourceModuleContext) {
+ sourceModule = ((ISourceModuleContext)goal.getContext()).getSourceModule();
+ }
}
@Override
public IGoal[] init() {
+ IGoal goal = produceNextSubgoal(null, null, null);
+ if (goal != null) {
+ return new IGoal[] { goal };
+ }
+ return IGoal.NO_GOALS;
+ }
+
+ private IGoal produceNextSubgoal(IGoal previousGoal,
+ IEvaluatedType previousResult, GoalState goalState) {
+ ExpressionTypeGoal typedGoal = (ExpressionTypeGoal) goal;
+ CallExpression expression = (CallExpression) typedGoal.getExpression();
+ if (sourceModule == null) {
+ return null;
+ }
+ // just starting to evaluate method, evaluate method receiver first:
+ if (state == STATE_INIT) {
+ ASTNode receiver = expression.getReceiver();
+ if (receiver == null) {
+ state = STATE_GOT_RECEIVER;
+ } else {
+ state = STATE_WAITING_RECEIVER;
+ return new ExpressionTypeGoal(goal.getContext(), receiver);
+ }
+ }
+
+ if (state == STATE_WAITING_RECEIVER) {
+ receiverType = previousResult;
+ previousResult = null;
+ if (receiverType == null) {
+ return null;
+ }
+ state = STATE_GOT_RECEIVER;
+ }
+
+ if (state == STATE_GOT_RECEIVER && receiverType != null) {
+ if (receiverType.getTypeName().equals(SymfonyCoreConstants.CONTAINER_INTERFACE) || receiverType.getTypeName().equals(SymfonyCoreConstants.CONTROLLER_PARENT)) {
+ return generateServiceTypeGoal();
+ } else {
+ IModelAccessCache accessCache = null;
+ if (goal.getContext() instanceof IModelCacheContext) {
+ accessCache = ((IModelCacheContext)goal.getContext()).getCache();
+ }
+ try {
+ IType[] types = PHPModelUtils.getTypes(receiverType.getTypeName(), sourceModule, 0, accessCache, null);
+ for (IType type : types) {
+ if (type.getFullyQualifiedName("\\").equals(SymfonyCoreConstants.CONTAINER_INTERFACE) || type.getFullyQualifiedName("\\").equals(SymfonyCoreConstants.CONTROLLER_PARENT)) {
+ return generateServiceTypeGoal();
+ }
+ IType[] superClasses = PHPModelUtils.getSuperClasses(type, accessCache != null ? accessCache.getSuperTypeHierarchy(type, null) : null);
+ for (IType sc : superClasses) {
+ if (sc.getFullyQualifiedName("\\").equals(SymfonyCoreConstants.CONTAINER_INTERFACE) || sc.getFullyQualifiedName("\\").equals(SymfonyCoreConstants.CONTROLLER_PARENT)) {
+ return generateServiceTypeGoal();
+ }
+ }
+
+ }
+ } catch (ModelException e) {
+ Logger.logException(e);
+ }
+ }
+ }
+ if (state == STATE_WAITING_SERVICE_TYPE) {
+ result = previousResult;
+ state = STATE_GOT_SERVICE_TYPE;
+ }
return null;
}
+ private IGoal generateServiceTypeGoal() {
+ state = STATE_WAITING_SERVICE_TYPE;
+ return new ServiceTypeGoal(goal.getContext(), serviceName);
+ }
+
@Override
public IGoal[] subGoalDone(IGoal subgoal, Object result, GoalState state) {
-
+ IGoal goal = produceNextSubgoal(subgoal, (IEvaluatedType) result, state);
+ if (goal != null) {
+ return new IGoal[] { goal };
+ }
return IGoal.NO_GOALS;
}
-
+
@Override
public Object produceResult() {
-
- if (service == null)
- return null;
-
- return new PHPClassType(service.getFullyQualifiedName());
-
+ return result;
}
}
View
53 ...e.symfony.core/src/com/dubture/symfony/core/goals/evaluator/ServiceTypeGoalEvaluator.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+
+ * This file is part of the Symfony eclipse plugin.
+ *
+ * (c) Dawid Pakuła <zulus@w3des.net>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ ******************************************************************************/
+package com.dubture.symfony.core.goals.evaluator;
+
+import org.eclipse.dltk.ti.GoalState;
+import org.eclipse.dltk.ti.ISourceModuleContext;
+import org.eclipse.dltk.ti.goals.IGoal;
+import org.eclipse.dltk.ti.types.IEvaluatedType;
+import org.eclipse.php.internal.core.typeinference.PHPClassType;
+import org.eclipse.php.internal.core.typeinference.evaluators.AbstractPHPGoalEvaluator;
+
+import com.dubture.symfony.core.goals.ServiceTypeGoal;
+import com.dubture.symfony.core.model.Service;
+import com.dubture.symfony.core.model.SymfonyModelAccess;
+
+@SuppressWarnings("restriction")
+public class ServiceTypeGoalEvaluator extends AbstractPHPGoalEvaluator {
+ protected ServiceTypeGoal goal;
+ private IEvaluatedType result = null;
+
+ public ServiceTypeGoalEvaluator(ServiceTypeGoal goal) {
+ super(goal);
+ this.goal = goal;
+
+ }
+
+ @Override
+ public IGoal[] init() {
+ if (goal.getContext() instanceof ISourceModuleContext) {
+ Service findService = SymfonyModelAccess.getDefault().findService(goal.getServiceId(),((ISourceModuleContext)goal.getContext()).getSourceModule().getScriptProject().getPath());
+ if (findService != null)
+ result = new PHPClassType(findService.getFullyQualifiedName());
+ }
+ return IGoal.NO_GOALS;
+ }
+
+ @Override
+ public Object produceResult() {
+ return result;
+ }
+
+ @Override
+ public IGoal[] subGoalDone(IGoal subgoal, Object result, GoalState state) {
+ return IGoal.NO_GOALS;
+ }
+}
View
6 com.dubture.symfony.core/src/com/dubture/symfony/core/preferences/SymfonyCoreConstants.java
@@ -64,7 +64,7 @@
public static final String VENDOR_PATH = "vendor";
public static final String CACHE_PATH = "app/cache";
public static final String LOG_PATH = "app/logs";
-
+
public static final String CACHE_PATTERN = "**/cache/";
public static final String LOG_PATTERN = "**/logs/";
public static final String SKELETON_PATTERN = "**/skeleton/";
@@ -85,6 +85,10 @@
public static final String SYMFONY_STANDARD_EDITION = "symfony/framework-standard-edition";
+ public static final String CONTROLLER_PARENT = "Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller";
+
+ public static final String CONTAINER_INTERFACE = "Symfony\\Component\\DependencyInjection\\ContainerInterface";
+
}
View
182 ...ure.symfony.core/src/com/dubture/symfony/core/util/text/SymfonyTextSequenceUtilities.java
@@ -1,8 +1,8 @@
/*******************************************************************************
* This file is part of the Symfony eclipse plugin.
- *
+ *
* (c) Robert Gruendler <r.gruendler@gmail.com>
- *
+ *
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
******************************************************************************/
@@ -19,24 +19,24 @@
/**
- *
+ *
* {@link SymfonyTextSequenceUtilities} is a utility class for {@link TextSequence}.
* Use it to check if you're inside a special pattern - ie. a servicecontainer
* getter function function like:
- *
+ *
* <pre>
- *
+ *
* $this->get(|
- *
- * or
- *
+ *
+ * or
+ *
* $this->container->get('
- *
+ *
* </pre>
- *
- *
+ *
+ *
* @see PHPTextSequenceUtilities
- *
+ *
* @author Robert Gruendler <r.gruendler@gmail.com>
*
*/
@@ -44,10 +44,12 @@
public class SymfonyTextSequenceUtilities {
private static final Pattern SERVICE_PATTERN = Pattern.compile("(\\$this->get\\(|\\$this->container->get\\(|->getContainer\\(\\)->get\\()");
-
- private static final Pattern REPOSITORY_PATTERN = Pattern.compile("\\->getRepository\\(");
-
- private static final Pattern TRANSLATION_PATTERN = Pattern.compile("(\\->transChoice\\(|\\->trans\\()");
+
+ private static final Pattern GET_PATTERN = Pattern.compile("(->get\\()");
+
+ private static final Pattern REPOSITORY_PATTERN = Pattern.compile("\\->getRepository\\(");
+
+ private static final Pattern TRANSLATION_PATTERN = Pattern.compile("(\\->transChoice\\(|\\->trans\\()");
private SymfonyTextSequenceUtilities() {
@@ -56,19 +58,19 @@ private SymfonyTextSequenceUtilities() {
/**
* Retrieve the startOffset of a ViewPath inside a textSeauence
- *
- *
+ *
+ *
* @param textSequence
* @return
*/
public static int readViewPathStartIndex(CharSequence textSequence) {
- int startPosition = textSequence.length() -1;
+ int startPosition = textSequence.length() -1;
return readLiteralStartIndex(textSequence, startPosition);
}
-
-
+
+
/**
* Checks for the existance of a service container function, ie. $this->get( or $this->container->get(
* @param sequence
@@ -78,7 +80,7 @@ public static int isInServiceContainerFunction(CharSequence sequence) {
Matcher matcher = SERVICE_PATTERN.matcher(sequence);
- while (matcher.find()) {
+ while (matcher.find()) {
int pos = matcher.end();
@@ -89,24 +91,46 @@ public static int isInServiceContainerFunction(CharSequence sequence) {
return pos;
}
- return -1;
+ return -1;
+ }
+ /**
+ * Checks for the existance of a get function, ie. ->get(
+ * @param sequence
+ * @return
+ */
+ public static int isGetFunction(CharSequence sequence) {
+
+ Matcher matcher = GET_PATTERN.matcher(sequence);
+
+ while (matcher.find()) {
+
+ int pos = matcher.end();
+
+ int lastMethodCall = sequence.toString().lastIndexOf("(");
+
+ if (lastMethodCall > pos)
+ return -1;
+
+ return pos;
+ }
+ return -1;
}
-
-
+
+
/**
* Check if the sequence is a method call for a doctrine repository ie
- *
+ *
* $this->getDoctrine()->getRepository(|
- *
+ *
* @param sequence
* @return
*/
public static int isInEntityFunctionParameter(CharSequence sequence) {
-
+
Matcher matcher = REPOSITORY_PATTERN.matcher(sequence);
- while (matcher.find()) {
+ while (matcher.find()) {
int pos = matcher.end();
@@ -117,18 +141,18 @@ public static int isInEntityFunctionParameter(CharSequence sequence) {
return pos;
}
- return -1;
-
-
-
+ return -1;
+
+
+
}
-
-
+
+
public static int isInTranslationFunctionParameter(CharSequence sequence) {
-
+
Matcher matcher = TRANSLATION_PATTERN.matcher(sequence);
- while (matcher.find()) {
+ while (matcher.find()) {
int pos = matcher.end();
@@ -139,8 +163,8 @@ public static int isInTranslationFunctionParameter(CharSequence sequence) {
return pos;
}
- return -1;
-
+ return -1;
+
}
public static String removeQuotes(String source) {
@@ -149,11 +173,11 @@ public static String removeQuotes(String source) {
}
-
+
/**
* Retrieve the service name from a PHP method call,
* ie: $this->get('session') will return the session literal.
- *
+ *
* @param sequence
* @return
*/
@@ -168,46 +192,46 @@ public static String getServiceFromMethodParam(TextSequence sequence) {
return null;
- return removeQuotes(source.substring(start, end));
+ return removeQuotes(source.substring(start, end));
}
-
-
+
+
/**
- *
+ *
* Extract the methodName of a TextSequence, ie,
- *
- * "$this->generate('" will return generate
- *
+ *
+ * "$this->generate('" will return generate
+ *
* @param statement
* @return
*/
public static String getMethodName(CharSequence statement) {
-
+
String text = statement.toString();
-
+
int start = text.indexOf("->");
int end = text.lastIndexOf("(");
-
+
int current = end;
-
+
while( current > 0 && current > start) {
- char c = text.charAt(current--);
+ char c = text.charAt(current--);
if (c == '>') {
- return text.substring(current+2, end);
+ return text.substring(current+2, end);
}
}
-
+
return null;
-
-
+
+
}
/**
* Check if the TextSequence is inside PHP method accepting
- * viewPath parameters.
- *
+ * viewPath parameters.
+ *
* @param statement
* @param project
* @return
@@ -215,10 +239,10 @@ public static String getMethodName(CharSequence statement) {
public static boolean isInViewPathFunctionParameter(TextSequence statement, IScriptProject project) {
String method = getMethodName(statement);
-
+
if (method == null)
return false;
-
+
return SymfonyModelAccess.getDefault().hasViewMethod(method, project);
}
@@ -226,36 +250,36 @@ public static boolean isInViewPathFunctionParameter(TextSequence statement, IScr
/**
* Check if the TextSequence is a function which accept route parameters.
- *
- *
+ *
+ *
* @param statement
* @param project
* @return
*/
public static boolean isInRouteFunctionParameter(TextSequence statement,
IScriptProject project) {
-
+
String method = getMethodName(statement);
if (method == null)
return false;
-
-
+
+
return SymfonyModelAccess.getDefault().hasRouteMethod(method, project);
}
-
-
+
+
/**
- *
+ *
* Read to the start index of a String literal.
- *
+ *
* @param textSequence
* @param startPosition
* @return
*/
public static int readLiteralStartIndex(CharSequence textSequence, int startPosition) {
-
+
while (startPosition > 0) {
char ch = textSequence.charAt(startPosition - 1);
@@ -270,25 +294,25 @@ public static int readLiteralStartIndex(CharSequence textSequence, int startPosi
}
- return startPosition;
-
+ return startPosition;
+
}
-
+
/**
- *
+ *
* Read to the end index of a String literal.
- *
+ *
* @param textSequence
* @param startPosition
* @return
*/
public static int readLiteralEndIndex(CharSequence textSequence, int startPosition) {
-
+
int max = textSequence.length() -1;
-
+
while (startPosition < max) {
char ch = textSequence.charAt(startPosition);
@@ -303,7 +327,7 @@ public static int readLiteralEndIndex(CharSequence textSequence, int startPositi
}
- return startPosition;
+ return startPosition;
}
}
View
4 com.dubture.symfony.test/workspace/services/ContainerInterface.php
@@ -0,0 +1,4 @@
+<?php
+namespace Symfony\Component\DependencyInjection;
+
+interface ContainerInterface {}
View
6 com.dubture.symfony.test/workspace/services/Controller.php
@@ -0,0 +1,6 @@
+<?php
+namespace Symfony\Bundle\FrameworkBundle\Controller;
+
+class Controller {
+
+}
View
2  com.dubture.symfony.test/workspace/services/testChainedServiceCompletion.pdtt
@@ -3,7 +3,7 @@ Should complete methods from the session service
--FILE--
<?
namespace NS;
-class A {
+class A implements \Symfony\Component\DependencyInjection\ContainerInterface {
function goo() {
$form = $this->get('form.factory');
$form->|
View
2  com.dubture.symfony.test/workspace/services/testParameterizedServiceMethodCompletion.pdtt
@@ -3,7 +3,7 @@ Should complete methods from the other service
--FILE--
<?
namespace NS;
-class B {
+class B extends \Symfony\Bundle\FrameworkBundle\Controller\Controller {
function roo() {
$this->get('other')->|
}
View
2  com.dubture.symfony.test/workspace/services/testServiceIdCompletion.pdtt
@@ -3,7 +3,7 @@ Should complete methods from the session service
--FILE--
<?
namespace NS;
-class A {
+class A implements \Symfony\Component\DependencyInjection\ContainerInterface {
function goo() {
$this->get('|');
}
View
5 com.dubture.symfony.test/workspace/services/testServiceMethodCompletion.pdtt
@@ -3,9 +3,10 @@ Should complete methods from the session service
--FILE--
<?
namespace NS;
-class A {
+class A implements \Symfony\Component\DependencyInjection\ContainerInterface {
function goo() {
- $this->get('session')->|
+ $variable = $this;
+ $variable->get('session')->|
}
}
?>
View
14 com.dubture.symfony.test/workspace/services/testServiceMethodCompletion2.pdtt
@@ -0,0 +1,14 @@
+--TEST--
+Should complete methods from the session service
+--FILE--
+<?
+namespace NS;
+class A extends \Symfony\Bundle\FrameworkBundle\Controller\Controller {
+ function goo() {
+ $this->get('session')->|
+ }
+}
+?>
+--EXPECT--
+method(sessionTest)
+method(someOtherMethod)
View
3  ...mfony.ui/src/com/dubture/symfony/ui/contentassist/SymfonyCompletionProposalCollector.java
@@ -80,8 +80,7 @@ protected IScriptCompletionProposal createScriptCompletionProposal(
return symfonyProposal;
}
- // don't complete anything else or we'll get duplicate entries
- return null;
+ return super.createScriptCompletionProposal(proposal);
}
private ScriptCompletionProposal generateSymfonyProposal(CompletionProposal typeProposal, ImageDescriptor descriptor) {
Please sign in to comment.
Something went wrong with that request. Please try again.