public static String filterTypeName(Class<?> type) { if (type != null) { if (!type.isPrimitive() && !(type.isArray() && ArrayTool.getLowerComponentType(type).isPrimitive())) { // for not primitives // return String.format( "%s.%s", ClassUtils.getPackageName(type), ClassUtils.getShortClassName(type)); } else { return ClassUtils.getShortClassName(type); } } return StringUtils.EMPTY; }
public static String getConstructorWithFields( String simpleClassName, Map<String, Class<?>> fields, int numberOfParamsForSuperConstructor) { StringBuilder buf = new StringBuilder(); if (fields.size() < 256) { // Generate constructor with parameters only in case where there are less than 256 arguments. // 255 arguments to the method is a Java limitation // buf.append(String.format("\n public %s(", simpleClassName)); Iterator<Entry<String, Class<?>>> fieldsIterator = fields.entrySet().iterator(); while (fieldsIterator.hasNext()) { Entry<String, Class<?>> field = fieldsIterator.next(); buf.append( String.format("%s %s", ClassUtils.getShortClassName(field.getValue()), field.getKey())); if (fieldsIterator.hasNext()) { buf.append(", "); } } buf.append(") {\n"); buf.append(" super("); fieldsIterator = fields.entrySet().iterator(); for (int i = 0; i < numberOfParamsForSuperConstructor; i++) { if (i != 0) { buf.append(", "); } buf.append(fieldsIterator.next().getKey()); } buf.append(");\n"); while (fieldsIterator.hasNext()) { Entry<String, Class<?>> field = fieldsIterator.next(); buf.append(String.format(" this.%s = %s;\n", field.getKey(), field.getKey())); } buf.append(" }\n"); } return buf.toString(); }
@Override public String toString() { String functionKeyString = this.getFunctionalKey().toString(); int indexOfCrochet = functionKeyString.indexOf('['); String fctKeyPropsStr = functionKeyString.substring(indexOfCrochet); return ClassUtils.getShortClassName(this.getClass()) + fctKeyPropsStr; }
/** * Gets the canonical name minus the package name from a String. * * <p>The string passed in is assumed to be a canonical name - it is not checked. * * @param canonicalName the class name to get the short name for * @return the canonical name of the class without the package name or an empty string * @since 2.4 */ public static String getShortCanonicalName(String canonicalName) { return ClassUtils.getShortClassName(getCanonicalName(canonicalName)); }
/** @author Olaf Lessenich */ public class ASTNodeArtifact extends Artifact<ASTNodeArtifact> { private static final Logger LOG = Logger.getLogger(ClassUtils.getShortClassName(ASTNodeArtifact.class)); /** * Initializes parser. * * @param p program */ private static void initParser(final Program p) { p.initJavaParser( new JavaParser() { @Override public CompilationUnit parse(final java.io.InputStream is, final String fileName) throws java.io.IOException, beaver.Parser.Exception { return new parser.JavaParser().parse(is, fileName); } }); } /** * Initializes a program. * * @return program */ private static Program initProgram() { Program program = new Program(); program.state().reset(); program.initBytecodeReader(new BytecodeParser()); initParser(program); return program; } /** * @param artifact artifact to create program from * @return ASTNodeArtifact */ public static ASTNodeArtifact createProgram(final ASTNodeArtifact artifact) { assert (artifact.astnode != null); assert (artifact.astnode instanceof Program); Program old = (Program) artifact.astnode; Program program; try { program = old.clone(); } catch (CloneNotSupportedException e) { program = new Program(); } ASTNodeArtifact p = new ASTNodeArtifact(program); p.deleteChildren(); return p; } /** Encapsulated ASTNode. */ private ASTNode<?> astnode = null; /** Constructor class. */ public ASTNodeArtifact() {} /** @param astnode astnode */ public ASTNodeArtifact(final ASTNode<?> astnode) { assert (astnode != null); this.astnode = astnode; } /** * Constructs an ASTNodeArtifact from a FileArtifact. * * @param artifact file artifact */ public ASTNodeArtifact(final FileArtifact artifact) { assert (artifact != null); setRevision(artifact.getRevision()); ASTNode<?> astnode; if (artifact.isEmptyDummy()) { astnode = new ASTNode<>(); setEmptyDummy(true); } else { Program p = initProgram(); p.addSourceFile(artifact.getPath()); astnode = p; } this.astnode = astnode; renumber(1, this); } /** * Returns the encapsulated JastAddJ ASTNode * * @return encapsulated ASTNode object from JastAddJ */ public final ASTNode<?> getASTNode() { return astnode; } /* * (non-Javadoc) * * @see * de.fosd.jdime.common.Artifact#addChild(de.fosd.jdime.common.Artifact) */ @Override public final ASTNodeArtifact addChild(final ASTNodeArtifact child) throws IOException { if (child.isConflict()) { child.setParent(this); children.add(child); return child; } ASTNodeArtifact myChild; try { myChild = new ASTNodeArtifact((ASTNode<?>) child.astnode.clone()); myChild.deleteChildren(); myChild.setRevision(child.getRevision()); myChild.setParent(this); myChild.astnode.setParent(astnode); myChild.setRevision(child.getRevision()); myChild.setNumber(child.getNumber()); myChild.cloneMatches(child); if (children == null) { initializeChildren(); } children.add(myChild); // astnode.flushCaches(); if (LOG.isTraceEnabled()) { LOG.trace("Added child " + myChild.getId() + " to parent node " + getId()); } return myChild; } catch (CloneNotSupportedException e) { throw new NotYetImplementedException(); } } @Override public final int compareTo(final ASTNodeArtifact o) { if (hasUniqueLabels()) { return astnode.dumpString().compareTo(o.astnode.dumpString()); } else { throw new RuntimeException("This artifact is not comparable."); } } /* * (non-Javadoc) * * @see * de.fosd.jdime.common.Artifact#copyArtifact(de.fosd.jdime.common.Artifact) */ @Override public final void copyArtifact(final ASTNodeArtifact destination) throws IOException { ASTNodeArtifact copy = destination.addChild(this); if (!isConflict() && hasChildren()) { for (ASTNodeArtifact child : getChildren()) { child.copyArtifact(copy); } } } /* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#createArtifact(boolean) */ @Override public final void createArtifact(final boolean isLeaf) throws IOException { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#createEmptyDummy() */ @Override public final ASTNodeArtifact createEmptyDummy() throws FileNotFoundException { ASTNodeArtifact dummy = new ASTNodeArtifact(); dummy.astnode = new ASTNode<>(); dummy.setEmptyDummy(true); dummy.setRevision(getRevision()); return dummy; } /** */ public final void deleteChildren() { while (hasChildren()) { ASTNodeArtifact child = getChild(0); child.astnode = null; children.remove(0); } } private static String getGraphvizId(ASTNodeArtifact artifact) { return "\"" + artifact.getId() + "\""; } /** * Returns the AST in dot-format. * * @param includeNumbers include node number in label if true * @return AST in dot-format. */ public final String dumpGraphvizTree(final boolean includeNumbers, int virtualcount) { assert (astnode != null); StringBuilder sb = new StringBuilder(); if (isConflict()) { // insert virtual node String conflictId = "\"c" + virtualcount + "\""; sb.append(conflictId); sb.append("[label=\"Conflict\", fillcolor = red, style = filled]") .append(System.lineSeparator()); // left alternative sb.append(left.dumpGraphvizTree(includeNumbers, virtualcount)); sb.append(conflictId) .append("->") .append(getGraphvizId(left)) .append("[label=\"") .append(left.getRevision()) .append("\"]") .append(";") .append(System.lineSeparator()); // right alternative sb.append(right.dumpGraphvizTree(includeNumbers, virtualcount)); sb.append(conflictId) .append("->") .append(getGraphvizId(right)) .append("[label=\"") .append(right.getRevision()) .append("\"]") .append(";") .append(System.lineSeparator()); } else { sb.append(getGraphvizId(this)).append("[label=\""); // node label if (includeNumbers) { sb.append("(").append(getNumber()).append(") "); } sb.append(astnode.dumpString()); sb.append("\""); if (hasMatches()) { sb.append(", fillcolor = green, style = filled"); } sb.append("];"); sb.append(System.lineSeparator()); // children for (ASTNodeArtifact child : getChildren()) { String childId = getGraphvizId(child); if (child.isConflict()) { virtualcount++; childId = "\"c" + virtualcount + "\""; } sb.append(child.dumpGraphvizTree(includeNumbers, virtualcount)); // edge sb.append(getGraphvizId(this)) .append("->") .append(childId) .append(";") .append(System.lineSeparator()); } } return sb.toString(); } /* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#dumpTree(java.lang.String) */ @Override protected final String dumpTree(final String indent) { assert (astnode != null); StringBuilder sb = new StringBuilder(); // node itself Matching<ASTNodeArtifact> m = null; // color if (!isConflict() && hasMatches()) { Set<Revision> matchingRevisions = matches.keySet(); // print color code String color = ""; for (Revision rev : matchingRevisions) { m = getMatching(rev); color = m.getColor().toShell(); } sb.append(color); } if (isConflict()) { sb.append(Color.RED.toShell()); sb.append(indent).append("(").append(getId()).append(") "); sb.append(this); sb.append(System.lineSeparator()); sb.append(Color.RED.toShell()); sb.append("<<<<<<< "); sb.append(System.lineSeparator()); // children if (left != null) { sb.append(left.dumpTree(indent)); } sb.append(Color.RED.toShell()); sb.append("======= "); sb.append(System.lineSeparator()); // children if (right != null) { sb.append(right.dumpTree(indent)); } sb.append(Color.RED.toShell()); sb.append(">>>>>>> "); sb.append(System.lineSeparator()); } else { sb.append(indent).append("(").append(getId()).append(") "); sb.append(this); if (hasMatches()) { assert (m != null); sb.append(" <=> (").append(m.getMatchingArtifact(this).getId()).append(")"); sb.append(Color.DEFAULT.toShell()); } sb.append(System.lineSeparator()); // children for (ASTNodeArtifact child : getChildren()) { sb.append(child.dumpTree(indent + " ")); } } return sb.toString(); } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ // @Override @Override public final boolean exists() { return astnode != null; } /* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#getId() */ @Override public final String getId() { return getRevision() + "-" + getNumber(); } @Override public final String getStatsKey(final MergeContext context) { return "nodes"; } /* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#hashCode() */ @Override public final int hashCode() { return astnode.dumpString().hashCode(); } @Override public final boolean hasUniqueLabels() { return ImportDecl.class.isAssignableFrom(astnode.getClass()) || Literal.class.isAssignableFrom(astnode.getClass()); } /* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#initializeChildren() */ @Override public final void initializeChildren() { assert (astnode != null); ArtifactList<ASTNodeArtifact> children = new ArtifactList<>(); for (int i = 0; i < astnode.getNumChildNoTransform(); i++) { ASTNodeArtifact child = new ASTNodeArtifact(astnode.getChild(i)); child.setParent(this); child.setRevision(getRevision()); children.add(child); } setChildren(children); } /* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#isEmpty() */ @Override public final boolean isEmpty() { return !hasChildren(); } /* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#isLeaf() */ @Override public final boolean isLeaf() { // TODO Auto-generated method stub return false; } /** * Returns whether declaration order is significant for this node. * * @return whether declaration order is significant for this node */ @Override public final boolean isOrdered() { return !ConstructorDecl.class.isAssignableFrom(astnode.getClass()) && !MethodDecl.class.isAssignableFrom(astnode.getClass()) && !InterfaceDecl.class.isAssignableFrom(astnode.getClass()) && !FieldDecl.class.isAssignableFrom(astnode.getClass()) && !FieldDeclaration.class.isAssignableFrom(astnode.getClass()) && !ImportDecl.class.isAssignableFrom(astnode.getClass()); } /** * Returns whether a node matches another node. * * @param other node to compare with. * @return true if the node matches another node. */ @Override public final boolean matches(final ASTNodeArtifact other) { assert (astnode != null); assert (other != null); assert (other.astnode != null); if (LOG.isDebugEnabled()) { LOG.debug("match(" + getId() + ", " + other.getId() + ")"); } if ((ImportDecl.class.isAssignableFrom(astnode.getClass()) || Literal.class.isAssignableFrom(astnode.getClass())) && other.astnode.getClass().equals(astnode.getClass())) { if (LOG.isDebugEnabled()) { LOG.debug( "Try Matching (prettyPrint): {" + astnode.prettyPrint() + "} and {" + other.astnode.prettyPrint() + "}"); } return astnode.prettyPrint().equals(other.astnode.prettyPrint()); } if (LOG.isDebugEnabled()) { LOG.debug( "Try Matching (dumpString): {" + astnode.dumpString() + "} and {" + other.astnode.dumpString() + "}"); } return astnode.dumpString().equals(other.astnode.dumpString()); } @Override public final void merge(MergeOperation<ASTNodeArtifact> operation, MergeContext context) throws IOException, InterruptedException { Objects.requireNonNull(operation, "operation must not be null!"); Objects.requireNonNull(context, "context must not be null!"); MergeStrategy<ASTNodeArtifact> astNodeStrategy = new ASTNodeStrategy(); if (LOG.isDebugEnabled()) { LOG.debug("Using strategy: " + astNodeStrategy); } MergeTriple<ASTNodeArtifact> triple = operation.getMergeTriple(); ASTNodeArtifact left = triple.getLeft(); ASTNodeArtifact right = triple.getRight(); ASTNodeArtifact target = operation.getTarget(); boolean safeMerge = true; int numChildNoTransform; try { numChildNoTransform = target.astnode.getClass().newInstance().getNumChildNoTransform(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException(); } if (!isRoot() && numChildNoTransform > 0) { // this language element has a fixed number of children, we need to be careful with this one boolean leftChanges = left.hasChanges(false); boolean rightChanges = right.hasChanges(false); if (leftChanges && rightChanges) { if (LOG.isTraceEnabled()) { LOG.trace("Target " + target.getId() + " expects a fixed amount of children."); LOG.trace("Both " + left.getId() + " and " + right.getId() + " contain changes."); LOG.trace("We will report a conflict instead of performing the merge."); } safeMerge = false; // to be safe, we will report a conflict instead of merging ASTNodeArtifact targetParent = target.getParent(); targetParent.removeChild(target); Operation<ASTNodeArtifact> conflictOp = new ConflictOperation<>(left, left, right, targetParent); conflictOp.apply(context); } } if (safeMerge) { astNodeStrategy.merge(operation, context); } if (!context.isQuiet() && context.hasOutput()) { System.out.print(context.getStdIn()); } } /** * Removes a child. * * @param child child that should be removed */ public final void removeChild(final ASTNodeArtifact child) { if (LOG.isTraceEnabled()) { LOG.trace("[" + getId() + "] removing child " + child.getId()); LOG.trace("children before removal: " + getChildren()); } Iterator<ASTNodeArtifact> it = children.iterator(); ASTNodeArtifact elem; while (it.hasNext()) { elem = it.next(); if (elem == child) { it.remove(); } } if (LOG.isTraceEnabled()) { LOG.trace("children after removal: " + getChildren()); } } /** * Pretty-prints the AST to source code. * * @return Pretty-printed AST (source code) */ public final String prettyPrint() { assert (astnode != null); rebuildAST(); astnode.flushCaches(); if (LOG.isDebugEnabled()) { System.out.println(dumpTree()); } return astnode.prettyPrint(); } /** Rebuild the encapsulated ASTNode tree top down. This should be only called at the root node */ public final void rebuildAST() { if (isConflict()) { astnode.isConflict = true; astnode.jdimeId = getId(); if (left != null) { left.rebuildAST(); astnode.left = left.astnode; } if (right != null) { right.rebuildAST(); astnode.right = right.astnode; } } ASTNode<?>[] newchildren = new ASTNode[getNumChildren()]; for (int i = 0; i < getNumChildren(); i++) { ASTNodeArtifact child = getChild(i); newchildren[i] = child.astnode; newchildren[i].setParent(astnode); child.rebuildAST(); } astnode.jdimeChanges = hasChanges(); astnode.jdimeId = getId(); astnode.setChildren(newchildren); assert (isConflict() || getNumChildren() == astnode.getNumChildNoTransform()); } /* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#toString() */ @Override public final String toString() { assert (astnode != null); return astnode.dumpString(); } /* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#write(java.lang.String) */ @Override public final void write(final String str) throws IOException { // TODO Auto-generated method stub } @Override public final ASTNodeArtifact createConflictDummy( final ASTNodeArtifact type, final ASTNodeArtifact left, final ASTNodeArtifact right) throws FileNotFoundException { ASTNodeArtifact conflict; conflict = new ASTNodeArtifact(type.astnode.fullCopy()); conflict.setConflict(left, right); return conflict; } /** * Returns statistical data of the tree. stats[0]: number of nodes stats[1]: tree depth stats[2]: * maximum number of children * * @return statistics */ public final int[] getStats() { // 0: number of nodes, 1: tree depth, 2: max children int[] mystats = new int[3]; mystats[0] = 1; mystats[1] = 0; mystats[2] = getNumChildren(); for (int i = 0; i < getNumChildren(); i++) { int[] childstats = getChild(i).getStats(); mystats[0] += childstats[0]; if (childstats[1] + 1 > mystats[1]) { mystats[1] = childstats[1] + 1; } if (childstats[2] > mystats[2]) { mystats[2] = childstats[2]; } } return mystats; } public final ASTStats getStats(Revision revision, LangElem level, boolean isFragment) { StatsElement nodeStats = new StatsElement(); StatsElement toplevelnodeStats = new StatsElement(); StatsElement classlevelnodeStats = new StatsElement(); StatsElement methodlevelnodeStats = new StatsElement(); StatsElement classStats = new StatsElement(); StatsElement methodStats = new StatsElement(); // clearly, this is a node nodeStats.incrementElements(); if (isConflict()) { nodeStats.incrementChanges(); nodeStats.incrementConflicting(); } else if ((revision == null && hasMatches()) || hasMatching(revision)) { nodeStats.incrementMatches(); } else { nodeStats.incrementChanges(); // added or deleted? if (hasMatches()) { // was deleted nodeStats.incrementDeleted(); } else { // was added nodeStats.incrementAdded(); } } StatsElement myStats = null; switch (level) { case TOPLEVELNODE: myStats = toplevelnodeStats; break; case CLASSLEVELNODE: myStats = classlevelnodeStats; break; case METHODLEVELNODE: myStats = methodlevelnodeStats; break; default: throw new NotYetImplementedException(); } assert (myStats != null); nodeStats.copy(myStats); assert myStats.getElements() != 0; // find out level for child nodes and adjust class and method counter if (astnode instanceof ClassDecl) { level = LangElem.CLASSLEVELNODE; myStats.copy(classStats); } else if (astnode instanceof MethodDecl || astnode instanceof ConstructorDecl) { level = LangElem.METHODLEVELNODE; myStats.copy(methodStats); } HashMap<String, StatsElement> diffstats = new HashMap<>(); diffstats.put(LangElem.NODE.toString(), nodeStats); diffstats.put(LangElem.TOPLEVELNODE.toString(), toplevelnodeStats); diffstats.put(LangElem.CLASSLEVELNODE.toString(), classlevelnodeStats); diffstats.put(LangElem.METHODLEVELNODE.toString(), methodlevelnodeStats); diffstats.put(LangElem.CLASS.toString(), classStats); diffstats.put(LangElem.METHOD.toString(), methodStats); ASTStats stats = new ASTStats(1, 1, getNumChildren(), diffstats, myStats.getChanges() != 0); boolean hasSubtreeChanges = stats.hasChanges(); if (!hasSubtreeChanges) { isFragment = false; } else if (!isFragment) { isFragment = true; stats.incrementFragments(); } boolean assertsEnabled = false; assert assertsEnabled = true; if (assertsEnabled) { for (String key : diffstats.keySet()) { StatsElement e = diffstats.get(key); assert (e.getElements() == e.getMatches() + e.getAdded() + e.getDeleted() + e.getConflicting()); assert (e.getChanges() == e.getAdded() + e.getDeleted() + e.getConflicting()); } } for (int i = 0; i < getNumChildren(); i++) { stats.add(getChild(i).getStats(revision, level, isFragment)); if (!hasSubtreeChanges && stats.hasChanges()) { hasSubtreeChanges = true; if (astnode instanceof ClassDecl) { stats.getDiffStats(LangElem.CLASS.toString()).incrementChanges(); } else if (astnode instanceof MethodDecl || astnode instanceof ConstructorDecl) { stats.getDiffStats(LangElem.METHOD.toString()).incrementChanges(); } } if (assertsEnabled) { for (String key : diffstats.keySet()) { StatsElement e = diffstats.get(key); assert (e.getElements() == e.getMatches() + e.getAdded() + e.getDeleted() + e.getConflicting()); } } } return stats; } }