mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-51945
This commit is contained in:
@@ -48,6 +48,8 @@ public class DfaUtil {
|
||||
private DfaUtil() {
|
||||
}
|
||||
|
||||
private static final MultiValuesMap<PsiVariable, PsiExpression> TOO_COMPLEX = new MultiValuesMap<PsiVariable, PsiExpression>();
|
||||
@Nullable("null means DFA analysis has failed (too complex to analyze)")
|
||||
public static Collection<PsiExpression> getCachedVariableValues(@Nullable final PsiVariable variable, @Nullable final PsiElement context) {
|
||||
if (variable == null || context == null) return Collections.emptyList();
|
||||
|
||||
@@ -66,7 +68,7 @@ public class DfaUtil {
|
||||
result = visitor.myValues;
|
||||
}
|
||||
else {
|
||||
result = null;
|
||||
result = TOO_COMPLEX;
|
||||
}
|
||||
}
|
||||
return new Result<MultiValuesMap<PsiVariable, PsiExpression>>(result, codeBlock);
|
||||
@@ -75,6 +77,7 @@ public class DfaUtil {
|
||||
context.putUserData(DFA_VARIABLE_INFO_KEY, cachedValue);
|
||||
}
|
||||
final MultiValuesMap<PsiVariable, PsiExpression> value = cachedValue.getValue();
|
||||
if (value == TOO_COMPLEX) return null;
|
||||
final Collection<PsiExpression> expressions = value == null ? null : value.get(variable);
|
||||
return expressions == null ? Collections.<PsiExpression>emptyList() : expressions;
|
||||
}
|
||||
@@ -82,7 +85,7 @@ public class DfaUtil {
|
||||
public static enum Nullness {
|
||||
NOT_NULL,NULL,UNKNOWN
|
||||
}
|
||||
// TRUE->not null, FALSE->null, null->unknown
|
||||
|
||||
@NotNull
|
||||
public static Nullness checkNullness(@Nullable final PsiVariable variable, @Nullable final PsiElement context) {
|
||||
if (variable == null || context == null) return Nullness.UNKNOWN;
|
||||
@@ -140,6 +143,7 @@ public class DfaUtil {
|
||||
return codeBlock;
|
||||
}
|
||||
|
||||
@Nullable("null means DFA analysis has failed (too complex to analyze)")
|
||||
public static Collection<? extends PsiElement> getPossibleInitializationElements(final PsiElement qualifierExpression) {
|
||||
if (qualifierExpression instanceof PsiMethodCallExpression) {
|
||||
return Collections.singletonList(qualifierExpression);
|
||||
@@ -147,7 +151,8 @@ public class DfaUtil {
|
||||
else if (qualifierExpression instanceof PsiReferenceExpression) {
|
||||
final PsiElement targetElement = ((PsiReferenceExpression)qualifierExpression).resolve();
|
||||
if (targetElement instanceof PsiVariable) {
|
||||
final Collection<? extends PsiElement> variableValues = getCachedVariableValues((PsiVariable)targetElement, (PsiExpression)qualifierExpression);
|
||||
final Collection<? extends PsiElement> variableValues = getCachedVariableValues((PsiVariable)targetElement, qualifierExpression);
|
||||
if (variableValues == null) return null;
|
||||
if (variableValues.isEmpty() && targetElement instanceof PsiField) {
|
||||
return getVariableAssignmentsInFile((PsiVariable)targetElement, false);
|
||||
}
|
||||
@@ -160,6 +165,7 @@ public class DfaUtil {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<PsiExpression> getVariableAssignmentsInFile(final PsiVariable psiVariable, final boolean literalsOnly) {
|
||||
final Ref<Boolean> modificationRef = Ref.create(Boolean.FALSE);
|
||||
final List<PsiExpression> list = ContainerUtil.mapNotNull(
|
||||
|
||||
@@ -17,9 +17,13 @@ package com.intellij.slicer;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.usages.TextChunk;
|
||||
import com.intellij.usages.UsagePresentation;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* User: cdr
|
||||
*/
|
||||
@@ -32,4 +36,30 @@ public class SliceDereferenceUsage extends SliceUsage {
|
||||
public void processChildren(Processor<SliceUsage> processor) {
|
||||
// no children
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public UsagePresentation getPresentation() {
|
||||
final UsagePresentation presentation = super.getPresentation();
|
||||
|
||||
return new UsagePresentation() {
|
||||
@NotNull
|
||||
public TextChunk[] getText() {
|
||||
return presentation.getText();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPlainText() {
|
||||
return presentation.getPlainText();
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
return presentation.getIcon();
|
||||
}
|
||||
|
||||
public String getTooltipText() {
|
||||
return "Variable dereferenced";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,19 +91,4 @@ public class SliceLeafValueRootNode extends SliceNode implements MyColoredTreeCe
|
||||
renderer.append("Other", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigate(boolean requestFocus) {
|
||||
getValue().navigate(requestFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNavigate() {
|
||||
return getValue().canNavigate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNavigateToSource() {
|
||||
return getValue().canNavigateToSource();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,19 +146,15 @@ public class SliceNode extends AbstractTreeNode<SliceUsage> implements Duplicate
|
||||
|
||||
protected void update(PresentationData presentation) {
|
||||
if (!initialized) {
|
||||
duplicate = targetEqualUsages.putNodeCheckDupe(this);
|
||||
if (!(getValue() instanceof SliceTooComplexDFAUsage)) duplicate = targetEqualUsages.putNodeCheckDupe(this);
|
||||
initialized = true;
|
||||
}
|
||||
if (presentation != null) {
|
||||
presentation.setChanged(presentation.isChanged() || changed);
|
||||
changed = false;
|
||||
if (duplicate != null) {
|
||||
presentation.setTooltip("Duplicate node");
|
||||
}
|
||||
|
||||
if (getValue() instanceof SliceDereferenceUsage) {
|
||||
presentation.setTooltip("Variable dereferenced");
|
||||
}
|
||||
presentation.setChanged(presentation.isChanged() || changed);
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.slicer;
|
||||
|
||||
import com.intellij.openapi.editor.markup.EffectType;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.usages.TextChunk;
|
||||
import com.intellij.usages.UsagePresentation;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* User: cdr
|
||||
*/
|
||||
public class SliceTooComplexDFAUsage extends SliceUsage {
|
||||
public SliceTooComplexDFAUsage(@NotNull PsiElement element, @NotNull SliceUsage parent, @NotNull PsiSubstitutor substitutor) {
|
||||
super(element, parent, substitutor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processChildren(Processor<SliceUsage> processor) {
|
||||
// no children
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public UsagePresentation getPresentation() {
|
||||
final UsagePresentation presentation = super.getPresentation();
|
||||
return new UsagePresentation() {
|
||||
@NotNull
|
||||
public TextChunk[] getText() {
|
||||
return new TextChunk[]{
|
||||
new TextChunk(new TextAttributes(Color.RED, null, null, EffectType.WAVE_UNDERSCORE, Font.PLAIN), getTooltipText())
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPlainText() {
|
||||
return presentation.getPlainText();
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
return presentation.getIcon();
|
||||
}
|
||||
|
||||
public String getTooltipText() {
|
||||
return "Too complex to analyze, analysis stoppped here";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,6 @@ public class SliceUsage extends UsageInfo2UsageAdapter {
|
||||
public void processChildren(Processor<SliceUsage> processor) {
|
||||
final PsiElement element = getElement();
|
||||
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
//indicator.setText2("<html><body>Searching for usages of "+ StringUtil.trimStart(SliceManager.getElementDescription(element),"<html><body>")+"</body></html>");
|
||||
indicator.checkCanceled();
|
||||
|
||||
final Processor<SliceUsage> uniqueProcessor =
|
||||
|
||||
@@ -73,8 +73,12 @@ public class SliceUtil {
|
||||
}
|
||||
if (expression instanceof PsiVariable) {
|
||||
PsiVariable variable = (PsiVariable)expression;
|
||||
|
||||
final Set<PsiExpression> expressions = new THashSet<PsiExpression>(DfaUtil.getCachedVariableValues(variable, original));
|
||||
Collection<PsiExpression> values = DfaUtil.getCachedVariableValues(variable, original);
|
||||
if (values == null) {
|
||||
SliceUsage stopUsage = createTooComplexDFAUsage(expression, parent, parentSubstitutor);
|
||||
return processor.process(stopUsage);
|
||||
}
|
||||
final Set<PsiExpression> expressions = new THashSet<PsiExpression>(values);
|
||||
PsiExpression initializer = variable.getInitializer();
|
||||
if (initializer != null && expressions.isEmpty()) expressions.add(initializer);
|
||||
for (PsiExpression exp : expressions) {
|
||||
@@ -232,6 +236,9 @@ public class SliceUtil {
|
||||
public static SliceUsage createSliceUsage(@NotNull PsiElement element, @NotNull SliceUsage parent, @NotNull PsiSubstitutor substitutor) {
|
||||
return new SliceUsage(simplify(element), parent, substitutor);
|
||||
}
|
||||
public static SliceUsage createTooComplexDFAUsage(@NotNull PsiElement element, @NotNull SliceUsage parent, @NotNull PsiSubstitutor substitutor) {
|
||||
return new SliceTooComplexDFAUsage(simplify(element), parent, substitutor);
|
||||
}
|
||||
|
||||
static boolean processParameterUsages(@NotNull final PsiParameter parameter, @NotNull final Processor<SliceUsage> processor, @NotNull final SliceUsage parent,
|
||||
@NotNull final PsiSubstitutor parentSubstitutor) {
|
||||
|
||||
+7
-8
@@ -18,9 +18,7 @@ package org.intellij.plugins.intelliLang.util;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInspection.dataFlow.DfaUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import org.intellij.plugins.intelliLang.Configuration;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -37,7 +35,6 @@ import java.util.concurrent.ConcurrentMap;
|
||||
* This is a quite simplified implementation at the moment.
|
||||
*/
|
||||
public class SubstitutedExpressionEvaluationHelper {
|
||||
private static final Key<CachedValue<ConcurrentMap<PsiElement, Object>>> COMPUTED_MAP_KEY = Key.create("COMPUTED_MAP_KEY");
|
||||
|
||||
private final PsiConstantEvaluationHelper myHelper;
|
||||
private final Configuration myConfiguration;
|
||||
@@ -78,12 +75,14 @@ public class SubstitutedExpressionEvaluationHelper {
|
||||
if (resolved instanceof PsiVariable) {
|
||||
resolvedType = ((PsiVariable)resolved).getType();
|
||||
final Collection<PsiExpression> values =
|
||||
!useDfa? Collections.<PsiExpression>emptyList() : DfaUtil.getCachedVariableValues(((PsiVariable)resolved), o);
|
||||
!useDfa? Collections.<PsiExpression>emptyList() : DfaUtil.getCachedVariableValues((PsiVariable)resolved, o);
|
||||
// return the first computed value as far as we do not support multiple injection
|
||||
for (PsiExpression value : values) {
|
||||
final Object computedValue = auxEvaluator.computeExpression(value, this);
|
||||
if (computedValue != null) {
|
||||
return computedValue;
|
||||
if (values != null) {
|
||||
for (PsiExpression value : values) {
|
||||
final Object computedValue = auxEvaluator.computeExpression(value, this);
|
||||
if (computedValue != null) {
|
||||
return computedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user