下面列出了com.intellij.psi.PsiRecursiveElementWalkingVisitor#com.jetbrains.php.lang.psi.elements.FunctionReference 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Nullable
@Override
public PhpType getType(PsiElement psiElement) {
if (psiElement instanceof FunctionReference) {
String subject = ((FunctionReference) psiElement).getSignature();
String parameters = StringUtils.join(PhpTypeProviderUtil.getReferenceSignatures((FunctionReference) psiElement), PARAMETER_SEPARATOR);
// done also by PhpStorm; is this suitable? reduce parameters maybe to limit to one on longer values?
if (subject.length() <= 200 && parameters.length() <= 300) {
return new PhpType().add("#" + this.getKey() + subject + '\u0198' + parameters);
} else if(subject.length() <= 200) {
// fallback on long parameter; to support at least some other features
return new PhpType().add("#" + this.getKey() + subject + '\u0198');
}
}
return null;
}
private void visitFunctionReference(FunctionReference functionReference) {
if (!"view".equals(functionReference.getName())) {
return;
}
PsiElement[] parameters = functionReference.getParameters();
if (parameters.length < 1 || !(parameters[0] instanceof StringLiteralExpression)) {
return;
}
String contents = ((StringLiteralExpression) parameters[0]).getContents();
if (StringUtils.isBlank(contents)) {
return;
}
views.add(Pair.create(contents, parameters[0]));
}
public static boolean isFunctionReference(@NotNull PsiElement psiElement, @NotNull String functionName, int parameterIndex) {
PsiElement parameterList = psiElement.getParent();
if(!(parameterList instanceof ParameterList)) {
return false;
}
ParameterBag index = PhpElementsUtil.getCurrentParameterIndex(psiElement);
if(index == null || index.getIndex() != parameterIndex) {
return false;
}
PsiElement functionCall = parameterList.getParent();
if(!(functionCall instanceof FunctionReference)) {
return false;
}
return functionName.equals(((FunctionReference) functionCall).getName());
}
public static boolean isFunctionReference(@NotNull PsiElement psiElement, @NotNull String functionName, int parameterIndex) {
PsiElement parameterList = psiElement.getParent();
PsiElement functionCall = parameterList.getParent();
if (parameterIndex != -1) {
if (!(parameterList instanceof ParameterList)) {
return false;
}
ParameterBag index = getCurrentParameterIndex(psiElement);
if (index == null || index.getIndex() != parameterIndex) {
return false;
}
} else {
functionCall = psiElement;
}
if (!(functionCall instanceof FunctionReference)) {
return false;
}
return functionName.equals(((FunctionReference) functionCall).getName());
}
private static boolean isFunctionParameter(PsiElement psiElement, int parameterIndex, String... funcName) {
PsiElement variableContext = psiElement.getContext();
if(!(variableContext instanceof ParameterList)) {
return false;
} else {
ParameterList parameterList = (ParameterList) variableContext;
PsiElement context = parameterList.getContext();
if(!(context instanceof FunctionReference)) {
return false;
} else {
FunctionReference methodReference = (FunctionReference) context;
String name = methodReference.getName();
return (name != null && Arrays.asList(funcName).contains(name) && getParameterIndex(parameterList, psiElement) == parameterIndex);
}
}
}
public static boolean isFunctionReference(@NotNull PsiElement psiElement, @NotNull String functionName, int parameterIndex) {
PsiElement parameterList = psiElement.getParent();
if(!(parameterList instanceof ParameterList)) {
return false;
}
ParameterBag index = PhpElementsUtil.getCurrentParameterIndex(psiElement);
if(index == null || index.getIndex() != parameterIndex) {
return false;
}
PsiElement functionCall = parameterList.getParent();
if(!(functionCall instanceof FunctionReference)) {
return false;
}
return functionName.equals(((FunctionReference) functionCall).getName());
}
private void visitFunctionReference(FunctionReference functionReference) {
if(!"view".equals(functionReference.getName())) {
return;
}
PsiElement[] parameters = functionReference.getParameters();
if(parameters.length < 1 || !(parameters[0] instanceof StringLiteralExpression)) {
return;
}
String contents = ((StringLiteralExpression) parameters[0]).getContents();
if(StringUtils.isBlank(contents)) {
return;
}
views.add(Pair.create(contents, parameters[0]));
}
private String[] collectMetaArgumentsSets(PsiElement position) {
Collection<String> argumentsSets = new ArrayList<>();
PhpNamespace root = PsiTreeUtil.getParentOfType(position, PhpNamespace.class);
if (root == null || !"PHPSTORM_META".equals(root.getName())) {
return new String[0];
}
Collection<ParameterList> arguments = PsiTreeUtil.findChildrenOfType(root, ParameterList.class);
for (ParameterList args : arguments) {
PsiElement parent = args.getParent();
if (!(parent instanceof FunctionReference) || !"registerArgumentsSet".equals(((FunctionReference)parent).getName())) {
continue;
}
StringLiteralExpression arg0 = PsiTreeUtil.findChildOfType(args, StringLiteralExpression.class);
if (arg0 == null) {
continue;
}
argumentsSets.add(arg0.getContents());
}
return argumentsSets.toArray(new String[0]);
}
@Override
public @Nullable HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file, @NotNull PsiElement target) {
ParameterList parameterList = PhpPsiUtil.getParentByCondition(target, true, ParameterList.INSTANCEOF, Statement.INSTANCEOF);
if (parameterList == null) {
return null;
}
FunctionReference functionCall = ObjectUtils.tryCast(parameterList.getParent(), FunctionReference.class);
String fqn = resolveFqn(functionCall);
if (!"\\pack".equals(fqn)) {
return null;
}
PsiElement[] parameters = parameterList.getParameters();
PsiElement selectedParameter = StreamEx.of(parameters).findFirst((p) -> p.getTextRange().containsOffset(editor.getCaretModel().getOffset())).orElse(null);
if (selectedParameter == null) {
return null;
}
int selectedIndex = PhpCodeInsightUtil.getParameterIndex(selectedParameter);
if (selectedIndex < 0 || selectedIndex >= parameters.length) {
return null;
}
return new PhpHighlightPackParametersUsagesHandler(editor, file, 0, selectedIndex, parameters);
}
@Override
public void visitElement(PsiElement element) {
if (element instanceof MethodReference) {
visitMethodReference((MethodReference) element);
}
if (element instanceof FunctionReference) {
visitFunctionReference((FunctionReference) element);
}
super.visitElement(element);
}
@NotNull
@Override
public PsiElementVisitor buildRealVisitor(@NotNull ProblemsHolder problemsHolder, boolean b) {
return new PhpElementVisitor() {
@Override
public void visitPhpFunctionCall(FunctionReference reference) {
if (DeprecationUtility.isDeprecated(problemsHolder.getProject(), reference)) {
problemsHolder.registerProblem(reference, "Global function scheduled for removal in upcoming TYPO3 version, consider using an alternative");
}
super.visitPhpFunctionCall(reference);
}
};
}
@Override
public void visitElement(PsiElement element) {
if(element instanceof FunctionReference) {
this.visitFunction((FunctionReference) element);
}
super.visitElement(element);
}
@Override
public void visitElement(PsiElement element) {
if(element instanceof MethodReference) {
visitMethodReference((MethodReference) element);
}
if(element instanceof FunctionReference) {
visitFunctionReference((FunctionReference) element);
}
super.visitElement(element);
}
private boolean isCallToHeaderFunc(PsiElement psiElement) {
FunctionReference function = PhpPsiUtil.getParentByCondition(psiElement, true, FunctionReference.INSTANCEOF, Statement.INSTANCEOF);
if (function == null) {
return false;
}
return "header".equals(function.getName());
}
@NotNull
@Override
public Result checkAutoPopup(char charTyped, @NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
if (!(file instanceof PhpFile)) {
return Result.CONTINUE;
}
if (charTyped != '%') {
return Result.CONTINUE;
}
int offset = editor.getCaretModel().getOffset();
PsiElement psiElement = file.findElementAt(offset);
ParameterList parameterList = PhpPsiUtil.getParentByCondition(psiElement, true, ParameterList.INSTANCEOF, Statement.INSTANCEOF);
if (parameterList != null) {
FunctionReference functionCall = ObjectUtils.tryCast(parameterList.getParent(), FunctionReference.class);
String fqn = PhpElementsUtil.resolveFqn(functionCall);
if (/*charTyped == '%' &&*/ PhpElementsUtil.isFormatFunction(fqn)) {
if (StringUtil.getPrecedingCharNum(editor.getDocument().getCharsSequence(), offset, '%') % 2 == 0) {
PhpCompletionUtil.showCompletion(editor);
}
}
}
return Result.CONTINUE;
}
public static FunctionReference getMetaFunctionReferenceWithName(PhpCallInstruction instruction, String name) {
FunctionReference reference = instruction.getFunctionReference();
if (!metaFunctionWithName(reference, name)) {
return null;
} else {
PsiElement[] parameters = reference.getParameters();
return parameters.length < 1 ? null : ObjectUtils.tryCast(parameters[0], FunctionReference.class);
}
}
private String getCallToFormatFunc(PsiElement psiElement) {
FunctionReference function = PhpPsiUtil.getParentByCondition(psiElement, true, FunctionReference.INSTANCEOF, Statement.INSTANCEOF);
if (function == null) {
return null;
}
return PhpElementsUtil.resolveFqn(function);
}
@Override
public void visitElement(PsiElement element) {
if (element instanceof VariableImpl) { //从模型变量收集
PsiReference reference = element.getReference();
if (reference == null) {
super.visitElement(element);
} else {
Set<String> types = ((VariableImpl) reference).getType().getTypes();
Project project = element.getProject();
for (String item : types) {
if (item.contains("\\model\\")) { //model子类
Collection<PhpClass> classesByFQN = PhpIndex.getInstance(project).getClassesByFQN(item);
for (PhpClass cls : classesByFQN) {
String table = Util.getTableByClass(cls, project);
this.visitor.visit(table, null);
}
}
}
}
} else if (element instanceof FunctionReference) { //从table, join, db, name 收集
PsiElement[] childrens = element.getChildren();
for (PsiElement paramList : childrens) {
if (paramList instanceof ParameterListImpl) {
if (paramList.getChildren().length > 0) {
PsiElement param = paramList.getChildren()[0];
// String methodName = ((FunctionReference) element).getName();
if (PsiElementUtil.isFunctionReference(param, "join", 0)) {
String text = param.getText().replace("'", "").replace("\"", "");
String[] s = text.split(" ");
this.visitor.visit(s[0], null);
} else if (PsiElementUtil.isFunctionReference(param, "table", 0)) {
addTable(param, 0);
} else if (PsiElementUtil.isFunctionReference(param, "db", 0) || PsiElementUtil.isFunctionReference(param, "name", 0)) {
addTable(param, 1);
}
}
} else if (paramList instanceof FunctionReference) { //链式调用方法
super.visitElement(element);
}
}
} else {
super.visitElement(element);
}
}
private static boolean metaFunctionWithName(FunctionReference reference, String name) {
return PhpLangUtil.equalsClassNames(reference.getName(), name) && META_NAMESPACE_PREFIX.equals(reference.getNamespaceName());
}
@Nullable
private static String resolveFqn(@Nullable FunctionReference reference) {
Function function = reference != null ? ObjectUtils.tryCast(reference.resolve(), Function.class) : null;
return function != null ? function.getFQN() : null;
}
private void visitFunction(FunctionReference expression) {
if(!PhpPsiHelper.isEnvFunction(expression)) return;
PsiElement[] parameters = expression.getParameters();
if(parameters.length == 0) return;
if(!(parameters[0] instanceof StringLiteralExpression)) return;
String key = ((StringLiteralExpression)parameters[0]).getContents();
collectedItems.add(new KeyUsagePsiElement(key, parameters[0]));
}
/**
* Checks whether this function reference is reference for env functions, like env or getenv
* @param functionReference Checking reference
* @return true if condition filled
*/
static boolean isEnvFunction(FunctionReference functionReference) {
String name = functionReference.getName();
return (name != null && Arrays.asList("getenv", "env").contains(name));
}