use of com.jetbrains.php.lang.psi.PhpFile in project phpinspectionsea by kalessil.
the class SwitchContinuationInLoopInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpContinue(@NotNull PhpContinue continueStatement) {
/* check if continue already defined with desired level */
if (null != continueStatement.getFirstPsiChild()) {
return;
}
boolean isSwitch = false;
PsiElement objParent = continueStatement.getParent();
while (null != objParent) {
/* reached file or callable */
if (objParent instanceof PhpFile || objParent instanceof Function) {
return;
}
/* check if should operate on loop-switch-continue analysis */
if (!isSwitch && objParent instanceof PhpSwitch) {
isSwitch = true;
}
/* when met a loop, complete analysis */
if (OpenapiTypesUtil.isLoop(objParent)) {
if (isSwitch) {
holder.registerProblem(continueStatement, MessagesPresentationUtil.prefixWithEa(message), ProblemHighlightType.GENERIC_ERROR, new UseContinue2LocalFix());
}
return;
}
objParent = objParent.getParent();
}
}
};
}
use of com.jetbrains.php.lang.psi.PhpFile in project phpinspectionsea by kalessil.
the class ClassConstantUsageCorrectnessInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpClassConstantReference(@NotNull ClassConstantReference constantReference) {
final String constantName = constantReference.getName();
if (constantName != null && constantName.equals("class")) {
final PsiElement reference = constantReference.getClassReference();
if (reference instanceof ClassReference) {
final ClassReference clazz = (ClassReference) reference;
final String referencedQn = reference.getText();
final PsiElement resolved = validReferences.contains(referencedQn) ? null : OpenapiResolveUtil.resolveReference(clazz);
if (resolved instanceof PhpClass) {
/* the resolved class will accumulate case issue in its FQN */
final List<String> variants = this.getVariants(clazz, (PhpClass) resolved);
if (!variants.isEmpty()) {
if (variants.stream().noneMatch(referencedQn::equals)) {
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(message));
}
variants.clear();
}
}
}
}
}
@NotNull
private List<String> getVariants(@NotNull ClassReference reference, @NotNull PhpClass clazz) {
final List<String> result = new ArrayList<>();
final String referenceText = reference.getText();
final String referenceTextLowercase = referenceText.toLowerCase();
if (referenceText.startsWith("\\")) {
/* FQN specified, resolve as we might have case issues there */
final Project project = holder.getProject();
final Collection<PhpClass> resolved = PhpIndex.getInstance(project).getClassesByFQN(referenceText);
if (!resolved.isEmpty()) {
result.add(resolved.iterator().next().getFQN());
}
} else {
PhpNamespace namespace = null;
PsiElement current = reference.getParent();
while (current != null && !(current instanceof PsiFile)) {
if (current instanceof PhpNamespace) {
namespace = (PhpNamespace) current;
break;
}
current = current.getParent();
}
final String classFqn = clazz.getFQN();
if (referenceText.contains("\\")) {
/* RQN specified, check if resolved class in the same NS */
final String NsFqn = namespace == null ? null : namespace.getFQN();
if (NsFqn != null && !NsFqn.equals("\\")) {
final String classFqnLowercase = classFqn.toLowerCase();
if (classFqnLowercase.startsWith(NsFqn.toLowerCase()) || classFqnLowercase.endsWith('\\' + referenceTextLowercase)) {
result.add(classFqn.substring(classFqn.length() - referenceText.length()));
}
}
/* RQN specified, check if resolved class in aliased NS */
final List<PhpUse> uses = new ArrayList<>();
if (namespace != null) {
final GroupStatement body = namespace.getStatements();
if (body != null) {
Arrays.stream(body.getStatements()).filter(statement -> statement instanceof PhpUseList).forEach(statement -> Collections.addAll(uses, ((PhpUseList) statement).getDeclarations()));
}
for (final PhpUse use : uses) {
final String alias = use.getAliasName();
if (alias != null && referenceTextLowercase.startsWith(alias.toLowerCase())) {
final PhpReference targetReference = use.getTargetReference();
if (targetReference != null) {
result.add(clazz.getFQN().replace(targetReference.getText(), alias).replaceAll("^\\\\", ""));
}
}
}
}
uses.clear();
} else {
final List<PhpUse> uses = new ArrayList<>();
if (namespace != null) {
/* find imports inside know namespace */
final GroupStatement body = namespace.getStatements();
if (body != null) {
Arrays.stream(body.getStatements()).filter(statement -> statement instanceof PhpUseList).forEach(statement -> Collections.addAll(uses, ((PhpUseList) statement).getDeclarations()));
}
} else {
final PsiFile file = reference.getContainingFile();
if (file instanceof PhpFile) {
/* find imports inside a file without namespace */
((PhpFile) file).getTopLevelDefs().values().stream().filter(definition -> definition instanceof PhpUse).forEach(definition -> uses.add((PhpUse) definition));
} else {
/* fallback, the most greedy strategy */
uses.addAll(PsiTreeUtil.findChildrenOfType(current, PhpUse.class));
}
}
/* imports (incl. aliases) */
for (final PhpUse use : uses) {
if (use.getFQN().equalsIgnoreCase(classFqn)) {
final String alias = use.getAliasName();
final PsiElement what = use.getFirstChild();
if (alias != null) {
/* alias as it is */
result.add(alias);
} else if (what instanceof ClassReference) {
/* resolve the imported class, as its the source for correct naming */
final PsiElement resolved = OpenapiResolveUtil.resolveReference((ClassReference) what);
if (resolved instanceof PhpClass) {
final PhpClass resolvedImport = (PhpClass) resolved;
final boolean importPrecise = resolvedImport.getFQN().endsWith(what.getText());
if (!importPrecise || !resolvedImport.getName().equals(referenceText)) {
result.add(resolvedImport.getFQN());
}
}
}
} else {
final String alias = use.getAliasName();
if (alias != null && alias.equalsIgnoreCase(referenceText)) {
result.add(alias);
}
}
}
uses.clear();
}
}
return result;
}
};
}
use of com.jetbrains.php.lang.psi.PhpFile in project phpinspectionsea by kalessil.
the class SlowArrayOperationsInLoopInspector 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 && greedyFunctions.contains(functionName)) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length > 1 && !(arguments[0] instanceof ArrayAccessExpression)) {
PsiElement parent = reference.getParent();
if (parent instanceof AssignmentExpression) {
/* false-positives: return/break as last group statement expression */
boolean canLoop = true;
if (OpenapiTypesUtil.isStatementImpl(parent = parent.getParent())) {
final PsiElement grandParent = parent.getParent();
if (grandParent instanceof GroupStatement) {
final PsiElement last = ExpressionSemanticUtil.getLastStatement((GroupStatement) grandParent);
canLoop = !(last instanceof PhpBreak) && !(last instanceof PhpReturn);
}
}
while (canLoop && parent != null && !(parent instanceof PhpFile) && !(parent instanceof Function)) {
if (OpenapiTypesUtil.isLoop(parent)) {
final PsiElement container = ((AssignmentExpression) reference.getParent()).getVariable();
if (container != null) {
for (final PsiElement argument : arguments) {
if (OpenapiEquivalenceUtil.areEqual(container, argument)) {
holder.registerProblem(reference, String.format(MessagesPresentationUtil.prefixWithEa(messageGreedyPattern), functionName));
return;
}
}
}
}
parent = parent.getParent();
}
}
}
}
}
@Override
public void visitPhpFor(@NotNull For forStatement) {
final Set<FunctionReference> references = new HashSet<>();
Arrays.stream(forStatement.getConditionalExpressions()).forEach(c -> {
if (c instanceof BinaryExpression) {
final BinaryExpression binary = (BinaryExpression) c;
Stream.of(binary.getLeftOperand(), binary.getRightOperand()).filter(p -> p instanceof FunctionReference).forEach(p -> references.add((FunctionReference) p));
}
});
references.stream().filter(OpenapiTypesUtil::isFunctionReference).forEach(r -> {
final String functionName = r.getName();
if (functionName != null && slowFunctions.contains(functionName)) {
final BinaryExpression condition = (BinaryExpression) r.getParent();
holder.registerProblem(condition, String.format(MessagesPresentationUtil.prefixWithEa(messageSlowPattern), functionName), ProblemHighlightType.GENERIC_ERROR, new ReduceRepetitiveCallsInForFix(holder.getProject(), forStatement, condition));
}
});
references.clear();
}
};
}
use of com.jetbrains.php.lang.psi.PhpFile in project yii2support by nvlad.
the class ViewMissedPhpDocInspection method buildVisitor.
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean b) {
return new PhpElementVisitor() {
@Override
public void visitPhpFile(PhpFile PhpFile) {
Project project = PhpFile.getProject();
ViewResolve resolve = ViewUtil.resolveView(PhpFile.getVirtualFile(), project);
if (resolve == null) {
return;
}
Map<String, String> params = getVariables(PhpFile);
Map<String, String> declaredVariables = new HashMap<>();
Collection<PhpDocVariable> variableCollection = PsiTreeUtil.findChildrenOfType(PhpFile, PhpDocVariable.class);
for (PhpDocVariable variable : variableCollection) {
declaredVariables.put(variable.getName(), variable.getType().toString());
}
Map<String, String> missedVariables = new HashMap<>();
for (String variableName : params.keySet()) {
if (!declaredVariables.containsKey(variableName)) {
missedVariables.put(variableName, params.get(variableName));
}
}
if (missedVariables.isEmpty()) {
return;
}
String problemDescription = "Missed View variable declaration.";
ViewMissedPhpDocLocalQuickFix quickFix = new ViewMissedPhpDocLocalQuickFix(PhpFile, missedVariables);
problemsHolder.registerProblem(PhpFile, problemDescription, quickFix);
}
private Map<String, String> getVariables(PhpFile phpFile) {
Collection<PsiReference> references = ReferencesSearch.search(phpFile).findAll();
Map<String, String> result = new HashMap<>();
Map<String, PhpType> viewArgumentCollection = new LinkedHashMap<>();
for (PsiReference reference : references) {
MethodReference methodReference = PsiTreeUtil.getParentOfType(reference.getElement(), MethodReference.class);
if (methodReference == null) {
continue;
}
Map<String, PhpType> params = RenderUtil.getViewArguments(methodReference);
for (Map.Entry<String, PhpType> entry : params.entrySet()) {
if (viewArgumentCollection.containsKey(entry.getKey())) {
PhpType.PhpTypeBuilder typeBuilder = new PhpType.PhpTypeBuilder();
typeBuilder.add(viewArgumentCollection.get(entry.getKey()));
typeBuilder.add(entry.getValue());
viewArgumentCollection.replace(entry.getKey(), typeBuilder.build());
} else {
viewArgumentCollection.put(entry.getKey(), entry.getValue());
}
}
}
for (String key : viewArgumentCollection.keySet()) {
result.put(key, viewArgumentCollection.get(key).toString());
}
return result;
}
};
}
use of com.jetbrains.php.lang.psi.PhpFile in project yii2support by nvlad.
the class ObjectFactoryCompletionProvider method addCompletions.
@Override
protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) {
if (getArrayCreation(completionParameters) == null && !(completionParameters.getPosition().getParent().getParent().getParent().getParent() instanceof ArrayCreationExpression) && !(completionParameters.getPosition().getParent().getParent().getParent() instanceof ArrayAccessExpression)) {
return;
}
ArrayCreationExpression arrayCreation = null;
// access to key of variable declared elsewhere
if (completionParameters.getPosition().getParent().getParent().getParent() instanceof ArrayAccessExpression) {
ArrayAccessExpression arrayAccess = (ArrayAccessExpression) completionParameters.getPosition().getParent().getParent().getParent();
PhpPsiElement value = arrayAccess.getValue();
if (value instanceof Variable)
arrayCreation = ObjectFactoryUtils.getArrayCreationByVarRef((Variable) value);
if (value instanceof FieldReference)
arrayCreation = ObjectFactoryUtils.getArrayCreationByFieldRef((FieldReference) value);
if (arrayCreation == null)
return;
// get parent array creation from inside of array
} else if (getArrayCreation(completionParameters) != null) {
arrayCreation = getArrayCreation(completionParameters);
} else if (completionParameters.getPosition().getParent().getParent().getParent().getParent() instanceof ArrayCreationExpression && completionParameters.getPosition().getParent().getParent().getParent() instanceof ArrayHashElement && completionParameters.getPosition().getParent().getParent().toString() != "Array value") {
arrayCreation = (ArrayCreationExpression) completionParameters.getPosition().getParent().getParent().getParent().getParent();
} else {
return;
}
PhpClass phpClass = null;
PhpFile file = (PhpFile) completionParameters.getOriginalFile();
PsiDirectory dir = file.getContainingDirectory();
phpClass = ObjectFactoryUtils.findClassByArrayCreation(arrayCreation, dir);
Hashtable<String, Object> uniqTracker = new Hashtable<>();
PhpExpression position = (PhpExpression) completionParameters.getPosition().getParent();
if (phpClass != null) {
for (Field field : ClassUtils.getWritableClassFields(phpClass)) {
uniqTracker.put(field.getName(), field);
LookupElementBuilder lookupBuilder = buildLookup(field, position);
completionResultSet.addElement(lookupBuilder);
}
for (Method method : ClassUtils.getClassSetMethods(phpClass)) {
if (uniqTracker.get(ClassUtils.getAsPropertyName(method)) == null) {
LookupElementBuilder lookupBuilder = buildLookup(method, position);
completionResultSet.addElement(lookupBuilder);
}
}
}
}
Aggregations