/** * Get array string values mapped with their PsiElements * * <p>["value", "value2"] */ @NotNull public static Map<String, PsiElement> getArrayValuesAsMap( @NotNull ArrayCreationExpression arrayCreationExpression) { List<PsiElement> arrayValues = PhpPsiUtil.getChildren( arrayCreationExpression, new Condition<PsiElement>() { @Override public boolean value(PsiElement psiElement) { return psiElement.getNode().getElementType() == PhpElementTypes.ARRAY_VALUE; } }); if (arrayValues == null) { return Collections.emptyMap(); } Map<String, PsiElement> keys = new HashMap<String, PsiElement>(); for (PsiElement child : arrayValues) { String stringValue = PhpElementsUtil.getStringValue(child.getFirstChild()); if (stringValue != null && StringUtils.isNotBlank(stringValue)) { keys.put(stringValue, child); } } return keys; }
@Nullable public static ArrayCreationExpression getCompletableArrayCreationElement(PsiElement psiElement) { // array('<test>' => '') if (PhpPatterns.psiElement(PhpElementTypes.ARRAY_KEY).accepts(psiElement.getContext())) { PsiElement arrayKey = psiElement.getContext(); if (arrayKey != null) { PsiElement arrayHashElement = arrayKey.getContext(); if (arrayHashElement instanceof ArrayHashElement) { PsiElement arrayCreationExpression = arrayHashElement.getContext(); if (arrayCreationExpression instanceof ArrayCreationExpression) { return (ArrayCreationExpression) arrayCreationExpression; } } } } // on array creation key dont have value, so provide completion here also // array('foo' => 'bar', '<test>') if (PhpPatterns.psiElement(PhpElementTypes.ARRAY_VALUE).accepts(psiElement.getContext())) { PsiElement arrayKey = psiElement.getContext(); if (arrayKey != null) { PsiElement arrayCreationExpression = arrayKey.getContext(); if (arrayCreationExpression instanceof ArrayCreationExpression) { return (ArrayCreationExpression) arrayCreationExpression; } } } return null; }
private void parseTypes2( Map<String, Collection<String>> map, Iterable<ArrayHashElement> elements, String parent) { Collection<String> types = map.get(parent); if (types == null) { types = new ArrayList<String>(); map.put(parent, types); } for (ArrayHashElement element : elements) { PhpPsiElement key = element.getKey(); if (key instanceof StringLiteralExpression) { // key String keyName = ((StringLiteralExpression) key).getContents(); types.add(keyName); String fullKeyName = parent.length() > 0 ? (parent + "." + keyName) : keyName; // value PhpPsiElement val = element.getValue(); if (val instanceof ArrayCreationExpression) { // recursive Iterable<ArrayHashElement> subElements = ((ArrayCreationExpression) val).getHashElements(); parseTypes2(map, subElements, fullKeyName); } else if (val instanceof FieldReference) { // reference to a field, where it's defined String classFqn = ((ClassReference) ((FieldReference) val).getClassReference()).getFQN(); for (PhpClass phpClass : PhpIndex.getInstance(element.getProject()).getClassesByFQN(classFqn)) { Field field = phpClass.findFieldByName(((FieldReference) val).getNameCS(), false); if (field.getDefaultValue() instanceof ArrayCreationExpression) { Iterable<ArrayHashElement> subElements = ((ArrayCreationExpression) field.getDefaultValue()).getHashElements(); parseTypes2(map, subElements, fullKeyName); } } } else { // get value type parseValueType(val); // try annotation PsiElement el2 = element; while (el2 != null && (el2 instanceof LeafPsiElement && ((LeafPsiElement) el2).getElementType() == PhpTokenTypes.opCOMMA || el2 instanceof PsiWhiteSpace)) { el2 = el2.getNextSibling(); } if (el2 instanceof PsiComment) { System.out.println("Comment for " + fullKeyName + ": " + el2.getText()); } } } } }
/** * 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); } } }
@Nullable public static MethodReferenceBag getMethodParameterReferenceBag( PsiElement psiElement, int wantIndex) { PsiElement variableContext = psiElement.getContext(); if (!(variableContext instanceof ParameterList)) { return null; } ParameterList parameterList = (ParameterList) variableContext; if (!(parameterList.getContext() instanceof MethodReference)) { return null; } ParameterBag currentIndex = PsiElementUtils.getCurrentParameterIndex(psiElement); if (currentIndex == null) { return null; } if (wantIndex >= 0 && currentIndex.getIndex() != wantIndex) { return null; } return new MethodReferenceBag( parameterList, (MethodReference) parameterList.getContext(), currentIndex); }
@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; }
/** * Find first variable declaration in parent scope of a given variable: * * <p>function() { $event = new FooEvent(); dispatch('foo', $event); } */ @Nullable public static String getFirstVariableTypeInScope(@NotNull Variable variable) { // parent search scope, eg Method else fallback to a grouped statement PsiElement searchScope = PsiTreeUtil.getParentOfType(variable, Function.class); if (searchScope == null) { searchScope = PsiTreeUtil.getParentOfType(variable, GroupStatement.class); } if (searchScope == null) { return null; } final String name = variable.getName(); if (name == null) { return null; } final String[] result = {null}; searchScope.acceptChildren( new PsiRecursiveElementVisitor() { @Override public void visitElement(PsiElement element) { if (element instanceof Variable && name.equals(((Variable) element).getName())) { PsiElement assignmentExpression = element.getParent(); if (assignmentExpression instanceof AssignmentExpression) { PhpPsiElement value = ((AssignmentExpression) assignmentExpression).getValue(); if (value instanceof NewExpression) { ClassReference classReference = ((NewExpression) value).getClassReference(); if (classReference != null) { String classSignature = classReference.getFQN(); if (StringUtils.isNotBlank(classSignature)) { result[0] = classSignature; } } } } } super.visitElement(element); } }); return result[0]; }
public static String getPrevSiblingAsTextUntil( PsiElement psiElement, ElementPattern pattern, boolean includeMatching) { String prevText = ""; for (PsiElement child = psiElement.getPrevSibling(); child != null; child = child.getPrevSibling()) { if (pattern.accepts(child)) { if (includeMatching) { return child.getText() + prevText; } return prevText; } else { prevText = child.getText() + prevText; } } return prevText; }
/** "DateTime", DateTime::class */ @Nullable public static PhpClass resolvePhpClassOnPsiElement(@NotNull PsiElement psiElement) { String dataClass = null; if (psiElement instanceof ClassConstantReference) { PsiElement lastChild = psiElement.getLastChild(); // @TODO: FOO::class find PhpElementTyp: toString provides "class" if ("class".equals(lastChild.getText())) { PhpExpression classReference = ((ClassConstantReference) psiElement).getClassReference(); if (classReference instanceof PhpReference) { dataClass = ((PhpReference) classReference).getFQN(); } } } else { dataClass = getStringValue(psiElement); } if (dataClass == null) { return null; } return getClassInterface(psiElement.getProject(), dataClass); }
@Nullable private static String getStringValue(@Nullable PsiElement psiElement, int depth) { if (psiElement == null || ++depth > 5) { return null; } if (psiElement instanceof StringLiteralExpression) { String resolvedString = ((StringLiteralExpression) psiElement).getContents(); if (StringUtils.isEmpty(resolvedString)) { return null; } return resolvedString; } if (psiElement instanceof Field) { return getStringValue(((Field) psiElement).getDefaultValue(), depth); } if (psiElement instanceof PhpReference) { PsiReference psiReference = psiElement.getReference(); if (psiReference == null) { return null; } PsiElement ref = psiReference.resolve(); if (ref instanceof PhpReference) { return getStringValue(psiElement, depth); } if (ref instanceof Field) { PsiElement resolved = ((Field) ref).getDefaultValue(); if (resolved instanceof StringLiteralExpression) { return ((StringLiteralExpression) resolved).getContents(); } } } return null; }