use of org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor in project intellij-community by JetBrains.
the class GroovyInlineLocalProcessor method collectRefs.
private static void collectRefs(final GrVariable variable, Instruction[] flow, final List<BitSet> writes, final int writeInstructionNumber, final ArrayList<UsageInfo> toInline) {
for (Instruction instruction : flow) {
final PsiElement element = instruction.getElement();
if (instruction instanceof ReadWriteVariableInstruction) {
if (((ReadWriteVariableInstruction) instruction).isWrite())
continue;
if (element instanceof GrVariable && element != variable)
continue;
if (!(element instanceof GrReferenceExpression))
continue;
final GrReferenceExpression ref = (GrReferenceExpression) element;
if (ref.isQualified() || ref.resolve() != variable)
continue;
final BitSet prev = writes.get(instruction.num());
if (writeInstructionNumber >= 0 && prev.cardinality() == 1 && prev.get(writeInstructionNumber)) {
toInline.add(new UsageInfo(ref));
} else if (writeInstructionNumber == -1 && prev.cardinality() == 0) {
toInline.add(new ClosureUsage(ref));
}
} else if (element instanceof GrClosableBlock) {
final BitSet prev = writes.get(instruction.num());
if (writeInstructionNumber >= 0 && prev.cardinality() == 1 && prev.get(writeInstructionNumber) || writeInstructionNumber == -1 && prev.cardinality() == 0) {
final Instruction[] closureFlow = ((GrClosableBlock) element).getControlFlow();
collectRefs(variable, closureFlow, ControlFlowUtils.inferWriteAccessMap(closureFlow, variable), -1, toInline);
}
} else if (element instanceof GrAnonymousClassDefinition) {
final BitSet prev = writes.get(instruction.num());
if (writeInstructionNumber >= 0 && prev.cardinality() == 1 && prev.get(writeInstructionNumber) || writeInstructionNumber == -1 && prev.cardinality() == 0) {
((GrAnonymousClassDefinition) element).acceptChildren(new GroovyRecursiveElementVisitor() {
@Override
public void visitField(@NotNull GrField field) {
GrExpression initializer = field.getInitializerGroovy();
if (initializer != null) {
Instruction[] flow = new ControlFlowBuilder(field.getProject()).buildControlFlow(initializer);
collectRefs(variable, flow, ControlFlowUtils.inferWriteAccessMap(flow, variable), -1, toInline);
}
}
@Override
public void visitMethod(@NotNull GrMethod method) {
GrOpenBlock block = method.getBlock();
if (block != null) {
Instruction[] flow = block.getControlFlow();
collectRefs(variable, flow, ControlFlowUtils.inferWriteAccessMap(flow, variable), -1, toInline);
}
}
@Override
public void visitClassInitializer(@NotNull GrClassInitializer initializer) {
GrOpenBlock block = initializer.getBlock();
Instruction[] flow = block.getControlFlow();
collectRefs(variable, flow, ControlFlowUtils.inferWriteAccessMap(flow, variable), -1, toInline);
}
});
}
}
}
}
use of org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor in project intellij-community by JetBrains.
the class ExtractUtil method collectUsedLocalVarsOrParamsDeclaredOutside.
private static Collection<GrVariable> collectUsedLocalVarsOrParamsDeclaredOutside(ExtractInfoHelper helper) {
final Collection<GrVariable> result = new HashSet<>();
final TextRange range = getRangeOfRefactoring(helper);
final int start = range.getStartOffset();
final int end = range.getEndOffset();
final GroovyRecursiveElementVisitor visitor = new GroovyRecursiveElementVisitor() {
@Override
public void visitReferenceExpression(@NotNull GrReferenceExpression ref) {
final PsiElement resolved = ref.resolve();
if ((resolved instanceof GrParameter || PsiUtil.isLocalVariable(resolved)) && resolved.isPhysical()) {
final int offset = resolved.getTextRange().getStartOffset();
//var is declared outside of selected code
if (offset < start || end <= offset) {
result.add((GrVariable) resolved);
}
}
}
};
final GrStatement[] statements = helper.getStatements();
for (GrStatement statement : statements) {
statement.accept(visitor);
}
return result;
}
use of org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor in project android by JetBrains.
the class GradleEditorModelParserFacade method fillContext.
/**
* Processes given PSI file and fills given context
* by {@link GradleEditorModelParseContext#getAssignments(Variable) corresponding assignments}.
*
* @param context context to fill
* @param psiFile psi file to parse
*/
private static void fillContext(@NotNull final GradleEditorModelParseContext context, @NotNull PsiFile psiFile) {
psiFile.acceptChildren(new GroovyPsiElementVisitor(new GroovyRecursiveElementVisitor() {
@Override
public void visitMethodCallExpression(GrMethodCallExpression methodCallExpression) {
Pair<String, TextRange> pair = GradleEditorValueExtractor.extractMethodName(methodCallExpression);
GrClosableBlock[] closureArguments = methodCallExpression.getClosureArguments();
if (pair == null || closureArguments.length > 1) {
super.visitMethodCallExpression(methodCallExpression);
return;
}
if (closureArguments.length == 0) {
if (methodCallExpression.getArgumentList().getAllArguments().length == 0) {
// This is a no-args method, so, we just register it for cases like 'mavenCentral()' or 'jcenter()'.
context.addCachedValue(NO_ARGS_METHOD_ASSIGNMENT_VALUE, TextRange.create(pair.second.getEndOffset(), methodCallExpression.getTextRange().getEndOffset()));
context.registerAssignmentFromCachedData(pair.first, pair.second, methodCallExpression);
}
return;
}
context.onMethodEnter(pair.getFirst());
try {
super.visitClosure(closureArguments[0]);
} finally {
context.onMethodExit();
}
}
@Override
public void visitApplicationStatement(GrApplicationStatement applicationStatement) {
Pair<String, TextRange> methodName = GradleEditorValueExtractor.extractMethodName(applicationStatement);
if (methodName == null) {
return;
}
GroovyPsiElement[] allArguments = applicationStatement.getArgumentList().getAllArguments();
if (allArguments.length == 1) {
context.resetCaches();
extractValueOrVariable(allArguments[0], context);
context.registerAssignmentFromCachedData(methodName.getFirst(), methodName.getSecond(), applicationStatement.getArgumentList());
}
}
@Override
public void visitAssignmentExpression(GrAssignmentExpression expression) {
// General idea is to try to extract variable from the given expression and, in case of success, try to extract rvalue and
// register corresponding assignment with them.
context.resetCaches();
extractValueOrVariable(expression.getLValue(), context);
Multimap<Variable, Location> vars = context.getCachedVariables();
if (vars.size() != 1) {
context.resetCaches();
return;
}
Map.Entry<Variable, Location> entry = vars.entries().iterator().next();
Variable lVariable = entry.getKey();
Location lVariableLocation = entry.getValue();
context.resetCaches();
GrExpression rValue = expression.getRValue();
if (rValue == null) {
return;
}
extractValueOrVariable(rValue, context);
if (context.getCachedValues().size() > 1) {
Value value = new Value("", new Location(context.getCurrentFile(), GradleEditorModelUtil.interestedRange(rValue)));
context.setCachedValues(Collections.singletonList(value));
}
context.registerAssignmentFromCachedData(lVariable, lVariableLocation, rValue);
context.resetCaches();
}
@Override
public void visitVariable(GrVariable variable) {
TextRange nameRange = null;
boolean lookForInitializer = false;
ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.findSingle(GroovyLanguage.INSTANCE);
for (PsiElement e = variable.getFirstChild(); e != null; e = e.getNextSibling()) {
ASTNode node = e.getNode();
if (node == null) {
continue;
}
if (!lookForInitializer) {
if (node.getElementType() == GroovyTokenTypes.mIDENT) {
nameRange = e.getTextRange();
} else if (node.getElementType() == GroovyTokenTypes.mASSIGN) {
if (nameRange == null) {
return;
}
lookForInitializer = true;
}
continue;
}
if (node.getElementType() == GroovyTokenTypes.mNLS || node.getElementType() == GroovyTokenTypes.mSEMI) {
break;
}
if (parserDefinition.getWhitespaceTokens().contains(node.getElementType())) {
continue;
}
extractValueOrVariable(e, context);
if (context.getCachedValues().size() > 1) {
Value value = new Value("", new Location(context.getCurrentFile(), GradleEditorModelUtil.interestedRange(e)));
context.setCachedValues(Collections.singletonList(value));
}
if (context.registerAssignmentFromCachedData(variable.getName(), nameRange, e)) {
return;
}
}
}
}));
}
use of org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor in project android by JetBrains.
the class LintIdeGradleDetector method visitBuildScript.
@Override
public void visitBuildScript(@NonNull final Context context, Map<String, Object> sharedData) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
final PsiFile psiFile = LintIdeUtils.getPsiFile(context);
if (!(psiFile instanceof GroovyFile)) {
return;
}
GroovyFile groovyFile = (GroovyFile) psiFile;
groovyFile.accept(new GroovyRecursiveElementVisitor() {
@Override
public void visitClosure(GrClosableBlock closure) {
String parentName = getClosureName(closure);
String parentParentName = null;
if (parentName != null) {
GrClosableBlock block = PsiTreeUtil.getParentOfType(closure, GrClosableBlock.class, true);
if (block != null) {
parentParentName = getClosureName(block);
}
}
if (parentName != null && isInterestingBlock(parentName, parentParentName)) {
for (PsiElement element : closure.getChildren()) {
if (element instanceof GrApplicationStatement) {
GrApplicationStatement call = (GrApplicationStatement) element;
GrExpression propertyExpression = call.getInvokedExpression();
GrCommandArgumentList argumentList = call.getArgumentList();
if (propertyExpression instanceof GrReferenceExpression) {
GrReferenceExpression propertyRef = (GrReferenceExpression) propertyExpression;
String property = propertyRef.getReferenceName();
//noinspection ConstantConditions
if (property != null && isInterestingProperty(property, parentName, parentParentName) && argumentList != null) {
String value = argumentList.getText();
checkDslPropertyAssignment(context, property, value, parentName, parentParentName, argumentList, call);
}
}
} else if (element instanceof GrAssignmentExpression) {
GrAssignmentExpression assignment = (GrAssignmentExpression) element;
GrExpression lValue = assignment.getLValue();
if (lValue instanceof GrReferenceExpression) {
GrReferenceExpression propertyRef = (GrReferenceExpression) lValue;
String property = propertyRef.getReferenceName();
if (property != null && isInterestingProperty(property, parentName, parentParentName)) {
GrExpression rValue = assignment.getRValue();
if (rValue != null) {
String value = rValue.getText();
checkDslPropertyAssignment(context, property, value, parentName, parentParentName, rValue, assignment);
// handle it here.
if (property.equals(ATTR_MIN_SDK_VERSION) || property.equals(ATTR_TARGET_SDK_VERSION)) {
int lValueEnd = lValue.getTextRange().getEndOffset();
int rValueStart = rValue.getTextRange().getStartOffset();
assert lValueEnd <= rValueStart;
DefaultPosition startPosition = new DefaultPosition(-1, -1, lValueEnd);
DefaultPosition endPosition = new DefaultPosition(-1, -1, rValueStart);
Location location = Location.create(context.file, startPosition, endPosition);
String message = String.format("Do not use assignment with the %1$s property (remove the '=')", property);
context.report(GradleDetector.IDE_SUPPORT, location, message, null);
}
}
}
}
}
}
}
super.visitClosure(closure);
}
@Override
public void visitApplicationStatement(GrApplicationStatement applicationStatement) {
GrClosableBlock block = PsiTreeUtil.getParentOfType(applicationStatement, GrClosableBlock.class, true);
String parentName = block != null ? getClosureName(block) : null;
String statementName = applicationStatement.getInvokedExpression().getText();
if (isInterestingStatement(statementName, parentName)) {
GrCommandArgumentList argumentList = applicationStatement.getArgumentList();
Map<String, String> namedArguments = Maps.newHashMap();
List<String> unnamedArguments = Lists.newArrayList();
for (GroovyPsiElement groovyPsiElement : argumentList.getAllArguments()) {
if (groovyPsiElement instanceof GrNamedArgument) {
GrNamedArgument namedArgument = (GrNamedArgument) groovyPsiElement;
GrExpression expression = namedArgument.getExpression();
if (expression == null || !(expression instanceof GrLiteral)) {
continue;
}
Object value = ((GrLiteral) expression).getValue();
if (value == null) {
continue;
}
namedArguments.put(namedArgument.getLabelName(), value.toString());
} else if (groovyPsiElement instanceof GrExpression) {
unnamedArguments.add(groovyPsiElement.getText());
}
}
checkMethodCall(context, statementName, parentName, namedArguments, unnamedArguments, applicationStatement);
}
super.visitApplicationStatement(applicationStatement);
}
});
}
});
}
use of org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor in project android by JetBrains.
the class UnusedResourcesProcessor method computeUnusedDeclarationElements.
@NotNull
private List<PsiElement> computeUnusedDeclarationElements(Map<Issue, Map<File, List<ProblemData>>> map) {
final List<PsiElement> elements = Lists.newArrayList();
// Make sure lint didn't put extra issues into the map
for (Issue issue : Lists.newArrayList(map.keySet())) {
if (issue != UnusedResourceDetector.ISSUE && issue != UnusedResourceDetector.ISSUE_IDS) {
map.remove(issue);
}
}
ApplicationManager.getApplication().assertReadAccessAllowed();
PsiManager manager = PsiManager.getInstance(myProject);
for (Issue issue : new Issue[] { UnusedResourceDetector.ISSUE, UnusedResourceDetector.ISSUE_IDS }) {
Map<File, List<ProblemData>> fileListMap = map.get(issue);
if (fileListMap != null && !fileListMap.isEmpty()) {
Map<File, PsiFile> files = Maps.newHashMap();
for (File file : fileListMap.keySet()) {
VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(file);
if (virtualFile != null) {
if (!virtualFile.isDirectory()) {
// Gradle model errors currently don't have source positions
PsiFile psiFile = manager.findFile(virtualFile);
if (psiFile != null) {
files.put(file, psiFile);
}
}
}
}
if (!files.isEmpty()) {
for (File file : files.keySet()) {
PsiFile psiFile = files.get(file);
if (psiFile == null) {
// where we only had the project directory as the location from the Gradle model
continue;
}
if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, psiFile)) {
continue;
}
List<ProblemData> problems = fileListMap.get(file);
if (psiFile.getFileType().isBinary()) {
// Delete the whole file
if (matchesFilter(fileListMap, file)) {
elements.add(psiFile);
}
} else {
ResourceFolderType folderType = ResourceHelper.getFolderType(psiFile);
if (folderType == null) {
// file; see for example http://b.android.com/220069.)
if (psiFile.getFileType() == GroovyFileType.GROOVY_FILE_TYPE && psiFile instanceof GroovyFile) {
((GroovyFile) psiFile).accept(new GroovyRecursiveElementVisitor() {
@Override
public void visitApplicationStatement(GrApplicationStatement applicationStatement) {
super.visitApplicationStatement(applicationStatement);
PsiMethod method = applicationStatement.resolveMethod();
if (method != null && method.getName().equals("resValue")) {
GrExpression[] args = applicationStatement.getArgumentList().getExpressionArguments();
if (args.length >= 3) {
Object typeString = GroovyConstantExpressionEvaluator.evaluate(args[0]);
Object nameString = GroovyConstantExpressionEvaluator.evaluate(args[1]);
// See if this is one of the unused resources
if (typeString != null && nameString != null) {
List<ProblemData> problems = fileListMap.get(VfsUtilCore.virtualToIoFile(psiFile.getVirtualFile()));
if (problems != null) {
for (ProblemData problem : problems) {
String unusedResource = UnusedResourceDetector.getUnusedResource(problem.getMessage(), TextFormat.RAW);
if (unusedResource != null && unusedResource.equals(SdkConstants.R_PREFIX + typeString + '.' + nameString)) {
elements.add(applicationStatement);
}
}
}
}
}
}
}
});
}
continue;
}
if (folderType != ResourceFolderType.VALUES) {
// also being deleted as unused
if (issue == UnusedResourceDetector.ISSUE_IDS) {
Map<File, List<ProblemData>> m = map.get(UnusedResourceDetector.ISSUE);
if (m != null && m.containsKey(file)) {
// Yes - skip
continue;
}
// Delete ranges within the file
addElementsInFile(elements, psiFile, problems);
} else {
// Unused non-value resource file: Delete the whole file
if (matchesFilter(fileListMap, file)) {
elements.add(psiFile);
}
}
} else {
addElementsInFile(elements, psiFile, problems);
}
}
}
}
}
}
return elements;
}
Aggregations