private static HashMap<String, String> getFormDefaultKeys( Project project, String formTypeName, HashMap<String, String> defaultValues, int depth) { PhpClass phpClass = FormUtil.getFormTypeToClass(project, formTypeName); if (phpClass == null) { return defaultValues; } String typeClass = phpClass.getPresentableFQN(); attachOnDefaultOptions(project, defaultValues, typeClass); // recursive search for parent form types PsiElement getParent = PhpElementsUtil.getPsiElementsBySignatureSingle( project, "#M#C\\" + phpClass.getPresentableFQN() + ".getParent"); if (getParent != null && depth < 10) { PhpReturn phpReturn = PsiTreeUtil.findChildOfType(getParent, PhpReturn.class); if (phpReturn != null) { PhpPsiElement returnValue = phpReturn.getFirstPsiChild(); if (returnValue instanceof StringLiteralExpression) { getFormDefaultKeys( project, ((StringLiteralExpression) returnValue).getContents(), defaultValues, depth++); } } } return defaultValues; }
@Nullable public static PsiElement getArrayKeyValueInsideSignaturePsi( PsiElement psiElementInsideClass, String callTo[], String methodName, String keyName) { PhpClass phpClass = PsiTreeUtil.getParentOfType(psiElementInsideClass, PhpClass.class); if (phpClass == null) { return null; } String className = phpClass.getPresentableFQN(); if (className == null) { return null; } for (String s : callTo) { // @TODO: replace signature PsiElement arrayKeyValueInsideSignature = PhpElementsUtil.getArrayKeyValueInsideSignaturePsi( psiElementInsideClass.getProject(), "#M#C\\" + className + "." + s, methodName, keyName); if (arrayKeyValueInsideSignature != null) { return arrayKeyValueInsideSignature; } } return null; }
private void buildPropertyMap(QueryBuilderScopeContext qb) { if (!collectProperties) { return; } for (QueryBuilderJoin join : qb.getJoinMap().values()) { String className = join.getResolvedClass(); if (className != null) { PhpClass phpClass = PhpElementsUtil.getClassInterface(project, className); if (phpClass != null) { qb.addPropertyAlias( join.getAlias(), new QueryBuilderPropertyAlias( join.getAlias(), null, new DoctrineModelField(join.getAlias()) .addTarget(phpClass) .setTypeName(phpClass.getPresentableFQN()))); // add entity properties for (DoctrineModelField field : EntityHelper.getModelFields(phpClass)) { qb.addPropertyAlias( join.getAlias() + "." + field.getName(), new QueryBuilderPropertyAlias(join.getAlias(), field.getName(), field)); } } } } }
/** * Try to visit possible class name for PsiElements with text like "Foo\|Bar", "Foo|\Bar", * "\Foo|\Bar" Cursor must have position in PsiElement * * @param psiElement the element context, cursor should be in it * @param cursorOffset current cursor editor eg from completion context * @param visitor callback on matching class */ public static void visitNamespaceClassForCompletion( PsiElement psiElement, int cursorOffset, ClassForCompletionVisitor visitor) { int cursorOffsetClean = cursorOffset - psiElement.getTextOffset(); if (cursorOffsetClean < 1) { return; } String content = psiElement.getText(); int length = content.length(); if (!(length >= cursorOffsetClean)) { return; } String beforeCursor = content.substring(0, cursorOffsetClean); boolean isValid; // espend\|Container, espend\Cont|ainer <- fallback to last full namespace // espend|\Container <- only on known namespace "espend" String namespace = beforeCursor; // if no backslash or its equal in first position, fallback on namespace completion int lastSlash = beforeCursor.lastIndexOf("\\"); if (lastSlash <= 0) { isValid = PhpIndexUtil.hasNamespace(psiElement.getProject(), beforeCursor); } else { isValid = true; namespace = beforeCursor.substring(0, lastSlash); } if (!isValid) { return; } // format namespaces and add prefix for fluent completion String prefix = ""; if (namespace.startsWith("\\")) { prefix = "\\"; } else { namespace = "\\" + namespace; } // search classes in current namespace and child namespaces for (PhpClass phpClass : PhpIndexUtil.getPhpClassInsideNamespace(psiElement.getProject(), namespace)) { String presentableFQN = phpClass.getPresentableFQN(); if (presentableFQN != null && fr.adrienbrault.idea.symfony2plugin.util.StringUtils.startWithEqualClassname( presentableFQN, beforeCursor)) { visitor.visit(phpClass, presentableFQN, prefix); } } }
public static boolean isTestClass(@NotNull PhpClass phpClass) { if (PhpUnitUtil.isTestClass(phpClass)) { return true; } String fqn = phpClass.getPresentableFQN(); if (fqn == null) { return false; } return fqn.contains("\\Test\\") || fqn.contains("\\Tests\\"); }
private static void attachOnDefaultOptions( Project project, HashMap<String, String> defaultValues, String typeClass) { PsiElement setDefaultOptions = PhpElementsUtil.getPsiElementsBySignatureSingle( project, "#M#C\\" + typeClass + ".setDefaultOptions"); if (setDefaultOptions == null) { return; } Collection<MethodReference> tests = PsiTreeUtil.findChildrenOfType(setDefaultOptions, MethodReference.class); for (MethodReference methodReference : tests) { // instance check // methodReference.getSignature().equals("#M#C\\Symfony\\Component\\OptionsResolver\\OptionsResolverInterface.setDefaults") if (PhpElementsUtil.isEqualMethodReferenceName(methodReference, "setDefaults")) { PsiElement[] parameters = methodReference.getParameters(); if (parameters.length > 0 && parameters[0] instanceof ArrayCreationExpression) { for (String key : PhpElementsUtil.getArrayCreationKeys((ArrayCreationExpression) parameters[0])) { defaultValues.put(key, typeClass); } } } // support: parent::setDefaultOptions($resolver) // Symfony\Component\Form\Extension\Core\Type\FormType:setDefaultOptions if (PhpElementsUtil.isEqualMethodReferenceName(methodReference, "setDefaultOptions") && methodReference.getReferenceType() == PhpModifier.State.PARENT) { PsiElement parentMethod = PhpElementsUtil.getPsiElementsBySignatureSingle( project, methodReference.getSignature()); if (parentMethod instanceof Method) { PhpClass phpClass = ((Method) parentMethod).getContainingClass(); if (phpClass != null) { attachOnDefaultOptions(project, defaultValues, phpClass.getPresentableFQN()); } } } } }
public static boolean isEqualClassName( @Nullable PhpClass phpClass, @Nullable String compareClassName) { if (phpClass == null || compareClassName == null) { return false; } String phpClassName = phpClass.getPresentableFQN(); if (phpClassName == null) { return false; } if (phpClassName.startsWith("\\")) { phpClassName = phpClassName.substring(1); } if (compareClassName.startsWith("\\")) { compareClassName = compareClassName.substring(1); } return phpClassName.equals(compareClassName); }
public static boolean isEqualClassName( @NotNull PhpClass phpClass, @NotNull PhpClass compareClassName) { return isEqualClassName(phpClass, compareClassName.getPresentableFQN()); }
public QueryBuilderScopeContext collect() { QueryBuilderScopeContext qb = new QueryBuilderScopeContext(); // doctrine needs valid root with an alias, try to find one in method references or scope Map<String, String> map = this.findRootDefinition(methodReferences); if (map.size() > 0) { Map.Entry<String, String> entry = map.entrySet().iterator().next(); qb.addTable(entry.getKey(), entry.getValue()); } for (MethodReference methodReference : methodReferences) { String name = methodReference.getName(); if (name != null) { collectParameter(qb, methodReference, name); collectJoins(qb, methodReference, name); collectSelects(qb, methodReference, name); collectSelectInForm(qb, methodReference, name); } } // first tableMap entry is root, we add several initial data if (qb.getTableMap().size() > 0) { Map.Entry<String, String> entry = qb.getTableMap().entrySet().iterator().next(); String className = entry.getKey(); PhpClass phpClass = PhpElementsUtil.getClassInterface(project, className); // add root select fields if (phpClass != null) { qb.addPropertyAlias( entry.getValue(), new QueryBuilderPropertyAlias( entry.getValue(), null, new DoctrineModelField(entry.getValue()) .addTarget(phpClass) .setTypeName(phpClass.getPresentableFQN()))); List<QueryBuilderRelation> relationList = new ArrayList<QueryBuilderRelation>(); // qb.addRelation(entry.getValue(), attachRelationFields(phpClass)); for (DoctrineModelField field : EntityHelper.getModelFields(phpClass)) { qb.addPropertyAlias( entry.getValue() + "." + field.getName(), new QueryBuilderPropertyAlias(entry.getValue(), field.getName(), field)); if (field.getRelation() != null && field.getRelationType() != null) { relationList.add(new QueryBuilderRelation(field.getName(), field.getRelation())); } } qb.addRelation(entry.getValue(), relationList); } QueryBuilderRelationClassResolver resolver = new QueryBuilderRelationClassResolver( project, entry.getValue(), entry.getKey(), qb.getRelationMap(), qb.getJoinMap()); resolver.collect(); } // we have a querybuilder which complete known elements now // se we can builder a property (field) map table from it this.buildPropertyMap(qb); return qb; }
private Map<String, String> findRootDefinition(Collection<MethodReference> methodReferences) { Map<String, String> roots = new HashMap<String, String>(); if (methodReferences.size() == 0) { return roots; } String rootAlias = null; String repository = null; for (MethodReference methodReference : methodReferences) { String methodReferenceName = methodReference.getName(); // get alias // ->createQueryBuilder('test'); if ("createQueryBuilder".equals(methodReferenceName)) { String possibleAlias = PhpElementsUtil.getStringValue( PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 0)); if (possibleAlias != null) { rootAlias = possibleAlias; } } // find repository class // getRepository('Foo')->createQueryBuilder('test'); if ("getRepository".equals(methodReferenceName)) { String possibleRepository = PhpElementsUtil.getStringValue( PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 0)); if (possibleRepository != null) { repository = possibleRepository; PhpClass phpClass = EntityHelper.resolveShortcutName(project, repository); if (phpClass != null) { repository = phpClass.getPresentableFQN(); } } } // $qb->from('Foo\Class', 'article') if ("from".equals(methodReferenceName)) { String table = PhpElementsUtil.getStringValue( PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 0)); String alias = PhpElementsUtil.getStringValue( PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 1)); if (table != null && alias != null) { PhpClass phpClass = EntityHelper.resolveShortcutName(project, table); if (phpClass != null) { table = phpClass.getPresentableFQN(); } roots.put(table, alias); } } } // we have a valid root so add it if (rootAlias != null && repository != null) { roots.put(repository, rootAlias); } // we found a alias but not a repository name, so try a scope search if we are inside repository // class // class implements \Doctrine\Common\Persistence\ObjectRepository, so search for model name of // "repositoryClass" if (rootAlias != null && repository == null) { MethodReference methodReference = methodReferences.iterator().next(); PhpClass phpClass = PsiTreeUtil.getParentOfType(methodReference, PhpClass.class); if (new Symfony2InterfacesUtil() .isInstanceOf(phpClass, "\\Doctrine\\Common\\Persistence\\ObjectRepository")) { for (DoctrineModel model : EntityHelper.getModelClasses(project)) { String className = model.getPhpClass().getPresentableFQN(); if (className != null) { PhpClass resolvedRepoName = EntityHelper.getEntityRepositoryClass(project, className); if (PhpElementsUtil.isEqualClassName(resolvedRepoName, phpClass.getPresentableFQN())) { roots.put(className, rootAlias); return roots; } } } } } // search on PhpTypeProvider // $er->createQueryBuilder() if (rootAlias != null && repository == null) { for (MethodReference methodReference : methodReferences) { if ("createQueryBuilder".equals(methodReference.getName())) { String signature = methodReference.getSignature(); int endIndex = signature.lastIndexOf(ObjectRepositoryTypeProvider.TRIM_KEY); if (endIndex != -1) { String parameter = signature.substring(endIndex + 1); int point = parameter.indexOf("."); if (point > -1) { parameter = parameter.substring(0, point); parameter = PhpTypeProviderUtil.getResolvedParameter( PhpIndex.getInstance(project), parameter); if (parameter != null) { PhpClass phpClass = EntityHelper.resolveShortcutName(project, parameter); if (phpClass != null && phpClass.getPresentableFQN() != null) { roots.put(phpClass.getPresentableFQN(), rootAlias); return roots; } } } } } } } return roots; }