Skip to content

Commit

Permalink
Log parsed decorators.
Browse files Browse the repository at this point in the history
Fixes #191.
  • Loading branch information
khatchad committed May 2, 2024
1 parent 9402bfe commit 335d343
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
import static com.ibm.wala.cast.python.util.Util.CLASS_METHOD_ANNOTATION_NAME;
import static com.ibm.wala.cast.python.util.Util.DYNAMIC_ANNOTATION_KEY;
import static com.ibm.wala.cast.python.util.Util.STATIC_METHOD_ANNOTATION_NAME;
import static com.ibm.wala.cast.python.util.Util.getNameStream;
import static com.ibm.wala.cast.python.util.Util.getNames;
import static com.ibm.wala.cast.python.util.Util.removeFileProtocolFromPath;
import static java.util.logging.Logger.getLogger;

import com.ibm.wala.cast.ir.translator.AbstractClassEntity;
import com.ibm.wala.cast.ir.translator.AbstractCodeEntity;
Expand All @@ -23,6 +25,7 @@
import com.ibm.wala.cast.python.ir.PythonCAstToIRTranslator;
import com.ibm.wala.cast.python.loader.DynamicAnnotatableEntity;
import com.ibm.wala.cast.python.types.PythonTypes;
import com.ibm.wala.cast.python.util.Util;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstAnnotation;
import com.ibm.wala.cast.tree.CAstEntity;
Expand Down Expand Up @@ -60,6 +63,8 @@
import java.util.LinkedList;
import java.util.Map;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.python.antlr.PythonTree;
import org.python.antlr.ast.Assert;
import org.python.antlr.ast.Assign;
Expand Down Expand Up @@ -141,6 +146,8 @@

public abstract class PythonParser<T> extends AbstractParser<T> implements TranslatorToCAst {

private static final Logger LOGGER = getLogger(PythonParser.class.getName());

private static boolean COMPREHENSION_IR = true;

private CAstType codeBody =
Expand Down Expand Up @@ -1186,10 +1193,13 @@ public String toString() {
};

annotations.add(cAstAnnotation);

if (LOGGER.isLoggable(Level.INFO))
Util.getName(cAstAnnotation).ifPresent(n -> LOGGER.info("Found decorator: " + n));
}

boolean staticMethod =
getNameStream(annotations).anyMatch(s -> s.equals(STATIC_METHOD_ANNOTATION_NAME));
getNames(annotations).stream().anyMatch(s -> s.equals(STATIC_METHOD_ANNOTATION_NAME));

CAstType functionType;
boolean isMethod =
Expand Down Expand Up @@ -1266,7 +1276,8 @@ public CAstNode getAST() {
if (function instanceof FunctionDef) {

boolean classMethod =
getNameStream(annotations).anyMatch(s -> s.equals(CLASS_METHOD_ANNOTATION_NAME));
getNames(annotations).stream()
.anyMatch(s -> s.equals(CLASS_METHOD_ANNOTATION_NAME));

// Only add object metadata for non-static and non-class methods.
if (isMethod && !staticMethod && !classMethod) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.ibm.wala.cast.python.loader;

import static com.ibm.wala.cast.python.types.PythonTypes.pythonLoader;
import static com.ibm.wala.cast.python.util.Util.getNameStream;
import static com.ibm.wala.cast.python.util.Util.getNames;
import static java.util.stream.Collectors.toList;

import com.ibm.wala.cast.ir.translator.AstTranslator.AstLexicalInformation;
Expand Down Expand Up @@ -80,7 +80,7 @@ public DynamicMethodBody(
// fill in the decorators.
// FIXME: Process annotations with parameters.
this.annotations =
getNameStream(entity.getAnnotations())
getNames(entity.getAnnotations()).stream()
.map(s -> "L" + s)
.map(TypeName::findOrCreate)
.map(tn -> TypeReference.findOrCreate(pythonLoader, tn))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.logging.Logger;
import java.util.stream.Stream;
import java.util.stream.Collectors;

public class Util {

Expand Down Expand Up @@ -70,27 +71,48 @@ public static List<File> getPathFiles(String pathSequence) {
}

/**
* Returns a {@link Stream} of annotation (decorator) names as {@link String}s from the given
* {@link Collection} of {@link CAstAnnotation}s.
* Returns a {@link Collection} of annotation (decorator) names as {@link String}s from the given
* {@link Collection} of {@link CAstAnnotation}s. The decorator names may be dot (.)-separated.
*
* @param annotations A {@link Collection} of {@link CAstAnnotation} for which to stream
* annotation (decorator) names.
* @return A {@link Stream} of names as {@link String}s corresponding to the given annotations
* @return A {@link Collection} of names as {@link String}s corresponding to the given annotations
* (decorators).
* @implNote The decorator names may not be fully-qualified. They are returned here as they are
* presented in the CAst.
*/
public static Stream<String> getNameStream(Collection<CAstAnnotation> annotations) {
if (annotations == null) return Stream.empty();

return annotations.stream()
.filter(a -> a.getType().equals(CAST_DYNAMIC_ANNOTATION))
.map(a -> a.getArguments().get(DYNAMIC_ANNOTATION_KEY))
.filter(Objects::nonNull)
.map(CAstNode.class::cast)
.map(n -> n.getChild(0))
.map(n -> n.getChild(0))
.map(CAstNode::getValue)
.filter(v -> v instanceof String)
.map(String.class::cast);
public static Collection<String> getNames(Collection<CAstAnnotation> annotations) {
return annotations.stream().map(Util::getName).flatMap(Optional::stream).toList();
}

public static Optional<String> getName(CAstAnnotation annotation) {
if (annotation.getType().equals(CAST_DYNAMIC_ANNOTATION)) {
CAstNode node = (CAstNode) annotation.getArguments().get(DYNAMIC_ANNOTATION_KEY);
List<String> decoratorSegments = getDecoratorSegments(node.getChild(0));
String decoratorName = decoratorSegments.stream().collect(Collectors.joining("."));
return Optional.of(decoratorName);
}

return Optional.empty();
}

private static List<String> getDecoratorSegments(CAstNode node) {
List<String> ret = new ArrayList<>();

if (node != null) {
List<CAstNode> children = node.getChildren();

for (CAstNode child : children) {
List<String> childDecoratorSegments = getDecoratorSegments(child);
ret.addAll(childDecoratorSegments);
}

Object value = node.getValue();

if (value != null && value instanceof String) ret.add((String) value);
}

return ret;
}

/**
Expand Down

0 comments on commit 335d343

Please sign in to comment.