use of com.jetbrains.php.lang.psi.elements.ParameterList in project phpinspectionsea by kalessil.
the class FileFunctionMissUseInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
final String functionName = reference.getName();
if (functionName == null || !functionName.equals("file")) {
return;
}
final PsiElement[] arguments = reference.getParameters();
if (arguments.length != 1) {
return;
}
/* function can be silenced, get parent for this case; validate parent structure */
PsiElement parent = reference.getParent();
if (parent instanceof UnaryExpression) {
final PsiElement operation = ((UnaryExpression) parent).getOperation();
if (OpenapiTypesUtil.is(operation, PhpTokenTypes.opSILENCE)) {
parent = parent.getParent();
}
}
if (!(parent instanceof ParameterList) || !OpenapiTypesUtil.isFunctionReference(parent.getParent())) {
return;
}
/* validate parent functions' name (implode or join) and amount of arguments */
final FunctionReference parentReference = (FunctionReference) parent.getParent();
final String parentName = parentReference.getName();
if (parentName == null || (!parentName.equals("implode") && !parentName.equals("join"))) {
return;
}
final PsiElement[] parentParams = parentReference.getParameters();
if (parentParams.length != 2) {
return;
}
/* validate if glue is not empty */
final StringLiteralExpression glue = ExpressionSemanticUtil.resolveAsStringLiteral(parentParams[0]);
if (glue != null && !glue.getContents().isEmpty()) {
return;
}
final String message = String.format(messagePattern, arguments[0].getText());
holder.registerProblem(parentReference, message, ProblemHighlightType.GENERIC_ERROR, new TheLocalFix());
}
};
}
use of com.jetbrains.php.lang.psi.elements.ParameterList in project phpinspectionsea by kalessil.
the class PrintfScanfArgumentsInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
final String functionName = reference.getName();
if (functionName == null || !functions.containsKey(functionName)) {
return;
}
/* resolve needed parameter */
final int neededPosition = functions.get(functionName);
final int minimumArgumentsForAnalysis = neededPosition + 1;
StringLiteralExpression pattern = null;
final PsiElement[] params = reference.getParameters();
if (params.length >= minimumArgumentsForAnalysis) {
pattern = ExpressionSemanticUtil.resolveAsStringLiteral(params[neededPosition]);
}
/* not available */
if (null == pattern) {
return;
}
final String content = pattern.getContents().trim();
if (!content.isEmpty()) {
/* find valid placeholders and extract positions specifiers as well */
int countWithoutPositionSpecifier = 0;
int maxPositionSpecifier = 0;
int countParsedAll = 0;
/* do normalization: %%, inline variables */
final String contentAdapted = content.replace("%%", "");
final String contentNoVars = contentAdapted.replaceAll("\\$\\{?\\$?[a-zA-Z0-9]+\\}?", "");
if (contentAdapted.length() != contentNoVars.length()) {
return;
}
final Matcher regexMatcher = regexPlaceHolders.matcher(contentAdapted);
while (regexMatcher.find()) {
++countParsedAll;
if (null != regexMatcher.group(2)) {
maxPositionSpecifier = Math.max(maxPositionSpecifier, Integer.parseInt(regexMatcher.group(2)));
continue;
}
++countWithoutPositionSpecifier;
}
final int expectedParametersCount = minimumArgumentsForAnalysis + Math.max(countWithoutPositionSpecifier, maxPositionSpecifier);
/* check for pattern validity */
final int parametersInPattern = StringUtils.countMatches(content.replace("%%", ""), "%");
if (countParsedAll != parametersInPattern) {
holder.registerProblem(params[neededPosition], messagePattern, ProblemHighlightType.GENERIC_ERROR);
return;
}
/* check for arguments matching */
if (expectedParametersCount != params.length) {
/* fscanf/sscanf will also return parsed values as an array if no values containers provided */
if (2 == params.length) {
final boolean returnsArray = functionName.equals("fscanf") || functionName.equals("sscanf");
final PsiElement parent = returnsArray ? reference.getParent() : null;
final PsiElement grandParent = parent == null ? null : parent.getParent();
if (returnsArray && parent != null) {
/* false-positive: dispatching/deconstructing into containers */
if (parent instanceof AssignmentExpression || grandParent instanceof AssignmentExpression) {
return;
} else /* false-positive: dispatching into calls */
if (parent instanceof ParameterList && grandParent instanceof FunctionReference) {
return;
}
}
}
/* false-positives: variadic */
if (OpenapiTypesUtil.is(params[params.length - 1].getPrevSibling(), PhpTokenTypes.opVARIADIC)) {
return;
}
final String message = messageParameters.replace("%c%", String.valueOf(expectedParametersCount));
holder.registerProblem(reference, message, ProblemHighlightType.GENERIC_ERROR);
}
}
}
};
}
use of com.jetbrains.php.lang.psi.elements.ParameterList in project phpinspectionsea by kalessil.
the class CascadingDirnameCallsInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
final String functionName = reference.getName();
if (functionName == null || !functionName.equals("dirname")) {
return;
}
final PsiElement[] arguments = reference.getParameters();
if (arguments.length != 1 && arguments.length != 2) {
return;
}
/* require PHP7+, where 2nd parameter has been added */
PhpLanguageLevel php = PhpProjectConfigurationFacade.getInstance(holder.getProject()).getLanguageLevel();
if (php.compareTo(PhpLanguageLevel.PHP700) < 0) {
return;
}
/* don't report nested calls, we want to report the one on top level */
final PsiElement parent = reference.getParent();
if (parent instanceof ParameterList && parent.getParent() instanceof FunctionReference) {
final FunctionReference parentReference = (FunctionReference) parent.getParent();
final String parentName = parentReference.getName();
if (parentName != null && parentName.equals("dirname")) {
final PsiElement[] parentArguments = parentReference.getParameters();
if (parentArguments.length == 1 || parentArguments.length == 2) {
return;
}
}
}
int directoryLevel = 0;
PsiElement argument = null;
final List<PsiElement> levels = new ArrayList<>();
FunctionReference current = reference;
while (current instanceof FunctionReference) {
final String currentName = current.getName();
if (currentName == null || !currentName.equals("dirname")) {
break;
}
final PsiElement[] currentArguments = current.getParameters();
if (currentArguments.length == 1) {
argument = currentArguments[0];
++directoryLevel;
} else if (currentArguments.length == 2) {
argument = currentArguments[0];
levels.add(currentArguments[1]);
} else {
break;
}
if (!(currentArguments[0] instanceof FunctionReference)) {
break;
}
current = (FunctionReference) currentArguments[0];
}
/* if no nested dirname calls, stop analysis */
if (current == reference) {
levels.clear();
return;
}
/* if we have 1+ nested call (top-level one is not considered) */
if (argument != null && arguments[0] != argument) {
/* process extracted level expressions: numbers to sum-up, expressions to stay */
final List<String> reported = new ArrayList<>();
for (PsiElement levelEntry : levels) {
try {
directoryLevel += Integer.parseInt(levelEntry.getText());
} catch (NumberFormatException fail) {
reported.add(levelEntry.getText());
}
}
levels.clear();
/* do not report cases with one level extraction */
if (1 == directoryLevel && 0 == reported.size()) {
reported.clear();
return;
}
/* generate the replacement expression */
reported.add(0, String.valueOf(directoryLevel));
final String replacement = "dirname(%a%, %l%)".replace("%a%", argument.getText()).replace("%l%", String.join(" + ", reported));
reported.clear();
final String message = messagePattern.replace("%e%", replacement);
holder.registerProblem(reference, message, new TheLocalFix(replacement));
}
}
};
}
use of com.jetbrains.php.lang.psi.elements.ParameterList in project yii2support by nvlad.
the class MethodUtils method findParamRefByElement.
@Nullable
public static PsiElement findParamRefByElement(PsiElement element) {
int limit = 10;
PsiElement prevElement = element;
PsiElement currElement = element.getParent();
while (limit > 0) {
if (currElement instanceof ParameterList)
return prevElement;
else {
prevElement = currElement;
currElement = currElement.getParent();
limit--;
}
}
return null;
}
use of com.jetbrains.php.lang.psi.elements.ParameterList in project yii2support by nvlad.
the class CompletionProvider method addCompletions.
@Override
protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) {
final PsiElement psiElement = completionParameters.getPosition();
final MethodReference method = PsiTreeUtil.getParentOfType(psiElement, MethodReference.class);
if (method == null || method.getParameters().length == 0) {
return;
}
if (!ViewUtil.isValidRenderMethod(method)) {
return;
}
PsiElement viewParameter = psiElement;
while (viewParameter != null && !(viewParameter.getParent() instanceof ParameterList)) {
viewParameter = viewParameter.getParent();
}
if (viewParameter == null || !viewParameter.equals(method.getParameters()[0])) {
return;
}
final ViewResolve resolve = ViewUtil.resolveView(viewParameter);
if (resolve == null) {
return;
}
final Project project = psiElement.getProject();
final GlobalSearchScope scope = GlobalSearchScope.projectScope(project);
final FileBasedIndex fileBasedIndex = FileBasedIndex.getInstance();
int prefixLength = resolve.key.length();
int lastSlashPosition = resolve.key.lastIndexOf('/');
if (lastSlashPosition != -1 && !resolve.key.endsWith("/")) {
prefixLength = lastSlashPosition + 1;
}
if (!completionParameters.isAutoPopup()) {
if (completionResultSet.getPrefixMatcher().getPrefix().startsWith("@") && lastSlashPosition == -1) {
final String prefix = completionResultSet.getPrefixMatcher().getPrefix();
completionResultSet = completionResultSet.withPrefixMatcher(prefix.substring(1));
prefixLength = 1;
} else {
completionResultSet = completionResultSet.withPrefixMatcher(resolve.key.substring(prefixLength));
}
}
if (completionResultSet.getPrefixMatcher().getPrefix().equals("@")) {
completionResultSet = completionResultSet.withPrefixMatcher("");
}
final String prefixFilter = resolve.key.substring(0, prefixLength);
final Set<String> keys = new HashSet<>();
fileBasedIndex.processAllKeys(ViewFileIndex.identity, key -> {
if (key.startsWith(prefixFilter)) {
keys.add(key);
}
return true;
}, scope, null);
final PsiManager psiManager = PsiManager.getInstance(project);
boolean localViewSearch = false;
if (resolve.from == ViewResolveFrom.View) {
final String value = PhpUtil.getValue(viewParameter);
localViewSearch = !value.startsWith("@") && !value.startsWith("//");
}
final String defaultViewExtension = '.' + Yii2SupportSettings.getInstance(psiElement.getProject()).defaultViewExtension;
for (String key : keys) {
Collection<ViewInfo> views = fileBasedIndex.getValues(ViewFileIndex.identity, key, scope);
for (ViewInfo view : views) {
if (!resolve.application.equals(view.application)) {
continue;
}
if (localViewSearch && !resolve.theme.equals(view.theme)) {
continue;
}
PsiFile psiFile = psiManager.findFile(view.getVirtualFile());
if (psiFile != null) {
String insertText = key.substring(prefixLength);
if (insertText.endsWith(defaultViewExtension)) {
insertText = insertText.substring(0, insertText.length() - defaultViewExtension.length());
}
completionResultSet.addElement(new ViewLookupElement(psiFile, insertText));
break;
} else {
System.out.println(view.fileUrl + " => not exists");
}
}
}
}
Aggregations