Skip to content

HelperVisitor more complex samples

Carsten Hammer edited this page Nov 4, 2021 · 2 revisions

Count all nodes and give out a list of the number of occurrences

The central class here is HelperVisitor. Because of some new features, the number of parameters changed.

  1. ReferenceHolder is a working object to hold information that is needed while visiting the nodes in the tree. You can use it to collect information or to share information.
  2. Set<ASTNode> nodesprocessed is to make sure that processing (changing) a node is not done twice. For cleanups/quickfixes you should not apply two different cleanups at the same time to the same node. This data structure is responsible to remember a node has already got a change and is not processed twice.

Using visit and visitend

	Set<ASTNode> nodesprocessed = null;
	ReferenceHolder<VisitorEnum, Integer> dataholder = new ReferenceHolder<>();
	HelperVisitor<ReferenceHolder<VisitorEnum,Integer>,VisitorEnum,Integer> hv = new HelperVisitor<>(nodesprocessed, dataholder);
	VisitorEnum.stream().forEach(ve -> {
		hv.add(ve, (node, holder) -> {
			holder.merge(VisitorEnum.fromNode(node), 1, Integer::sum);
			return true;
		});
	});
	VisitorEnum.stream().forEach(ve -> {
		hv.addEnd(ve, (node, holder) -> {
			holder.merge(VisitorEnum.fromNode(node), 1, Integer::sum);
		});
	});
	hv.build(cunit1);
	for(VisitorEnum ve: dataholder.keySet()) {
		System.out.println(dataholder.get(ve)+"\t"+ve.name());
	}

The code given writes a list to sysout with the amount of occurrences of each kind of node like this

2	VariableDeclarationFragment
8	ExpressionStatement
2	TypeDeclaration
4	SingleVariableDeclaration
8	MethodInvocation
10	QualifiedName
2	MethodDeclaration
2	ImportDeclaration
58	SimpleName
2	PrimitiveType
2	VariableDeclarationStatement
2	ParameterizedType
4	Modifier
4	Block
2	NullLiteral
2	EnhancedForStatement
8	SimpleType
2	CompilationUnit
2	PackageDeclaration

Only using visit

	private void countVisits(ASTNode node, ReferenceHolder<VisitorEnum, Integer> holder) {
		holder.merge(VisitorEnum.fromNode(node), 1, Integer::sum);
	}

	ReferenceHolder<VisitorEnum, Integer> dataholder = new ReferenceHolder<>();
	HelperVisitor.callVisitor(cunit1, EnumSet.allOf(VisitorEnum.class), dataholder,null, this::countVisits);

	/**
	 * Presenting result
	 */
	dataholder.entrySet().stream().forEach(entry->{
		System.out.println(entry.getValue()+"\t"+entry.getKey().name());
	});

The code given writes a list to sysout with the amount of occurrences of each kind of node like this

1	VariableDeclarationStatement
4	SimpleType
1	NullLiteral
1	MethodDeclaration
1	PrimitiveType
1	EnhancedForStatement
2	SingleVariableDeclaration
1	VariableDeclarationFragment
2	Block
1	CompilationUnit
1	ImportDeclaration
1	PackageDeclaration
4	MethodInvocation
5	QualifiedName
2	Modifier
29	SimpleName
1	TypeDeclaration
4	ExpressionStatement
1	ParameterizedType

Collect information about nodes and present it

The central class here is HelperVisitor. Because of some new features, the number of parameters changed.

  1. ReferenceHolder is a working object to hold information that is needed while visiting the nodes in the tree. You can use it to collect information or to share information.
  2. Set<ASTNode> nodesprocessed is to make sure that processing (changing) a node is not done twice. For cleanups/quickfixes you should not apply two different cleanups at the same time to the same node. This data structure is responsible to remember a node has already got a change and is not processed twice.

Using visit and visitend

	ReferenceHolder<ASTNode, Integer> dataholder = new ReferenceHolder<>();
	HelperVisitor.callVisitor(cunit1,EnumSet.of(
		VisitorEnum.SingleVariableDeclaration,
		VisitorEnum.VariableDeclarationExpression,
		VisitorEnum.VariableDeclarationStatement,
		VisitorEnum.VariableDeclarationFragment), dataholder,null, (node,holder)->{
			holder.put(node, node.getStartPosition());
	});

	/**
	 * Presenting result
	 */
	dataholder.entrySet().stream().forEach(entry->{
		System.out.println(entry.getKey()+"\t"+entry.getValue()+"\t"+ASTNode.nodeClassForType(entry.getKey().getNodeType()));
	});

The code given writes a list to sysout. The first column is the node and the second is the character position.

Collection<String> arr 78 class org.eclipse.jdt.core.dom.SingleVariableDeclaration Collection coll=null; 106 class org.eclipse.jdt.core.dom.VariableDeclarationStatement String var 137 class org.eclipse.jdt.core.dom.SingleVariableDeclaration coll=null 117 class org.eclipse.jdt.core.dom.VariableDeclarationFragment

Modify search while searching

	Set<ASTNode> nodesprocessed = null;
	HelperVisitor<ReferenceHolder<String,NodeFound>,String,NodeFound> hv = new HelperVisitor<>(nodesprocessed, new ReferenceHolder<>());
	hv.addMethodInvocation("println",(node, holder) -> {
		System.out.println("Start "+node.getNodeType() + " :" + node);
		return true;
	});
	hv.addMethodInvocation((node, holder) -> {
		System.out.println("End "+node.getNodeType() + " :" + node);
		holder.getHelperVisitor().removeVisitor(VisitorEnum.MethodInvocation);
	});
	hv.build(cunit1);

Sample Plugins

Clone this wiki locally