All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.main.lombok.ast.Template Maven / Gradle / Ivy

Go to download

This is a very small fork of lombok.ast as some Android tools needed a few modifications. The normal repository for lombok.ast is here https://github.com/rzwitserloot/lombok.ast and our changes for 0.2.3 are in this pull request: https://github.com/rzwitserloot/lombok.ast/pull/8

The newest version!
package lombok.ast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import lombok.ast.grammar.Source;

public class Template {
	private static  N process(Source s, String name, Class type) {
		if (!s.getProblems().isEmpty()) {
			throw new AstException(null, "Can't parse snippet: " + s.getProblems().get(0).getMessage());
		}
		if (s.getNodes().isEmpty()) return null;
		if (s.getNodes().size() > 1) throw new AstException(null, "Can't parse snippet: more than one " + name + " in snippet");
		Node n = s.getNodes().get(0);
		if (type.isInstance(n)) return type.cast(n);
		throw new AstException(null, "Can't parse snippet: Not a " + name);
	}
	
	/**
	 * Parses one construct that is legal as a type member, and returns it.
	 * 
	 * Legal type members: 
    *
  • Constructor Declaration
  • *
  • Method Declaration
  • *
  • Static or Instance Initializer
  • *
  • Any type declaration
  • *
  • The empty declaration (lone semi-colon)
  • *
  • A variable declaration
  • *
* * Note that neither annotation method declarations nor enum constants will be parsed properly by this method. */ public static TypeMember parseMember(String source) throws AstException { Source s = new Source(source, "memberSnippet"); s.parseMember(); return process(s, "type member", TypeMember.class); } public static MethodDeclaration parseMethod(String source) throws AstException { Source s = new Source(source, "methodSnippet"); s.parseMember(); return process(s, "method", MethodDeclaration.class); } public static ConstructorDeclaration parseConstructor(String source) throws AstException { Source s = new Source(source, "constructorSnippet"); s.parseMember(); return process(s, "constructor", ConstructorDeclaration.class); } public static VariableDeclaration parseField(String source) throws AstException { Source s = new Source(source, "fieldSnippet"); s.parseMember(); return process(s, "field", VariableDeclaration.class); } public static VariableDefinition parseVariableDefinition(String source) throws AstException { Source s = new Source(source, "vardefSnippet"); s.parseMember(); return process(s, "vardef", VariableDefinition.class); } public static Statement parseStatement(String source) throws AstException { Source s = new Source(source, "statementSnippet"); s.parseStatement(); return process(s, "statement", Statement.class); } public static Expression parseExpression(String source) throws AstException { Source s = new Source(source, "expressionSnippet"); s.parseExpression(); return process(s, "expression", Expression.class); } /** * NB: Do not simply pass the result of {@code parseX} to this method; parsing is extremely slow. Instead, parse a template once, * and then pass this one result every time. The template will never modify the original. */ @SuppressWarnings("unchecked") public static Template of(N source) throws AstException { return new Template((N) source.copy()); } private final T node; private int location; private Node responsible; private List replacements = new ArrayList(); private int replacementsPointer = 0; private static class ReplacementOrder { String identifierToReplace, statementToReplace, expressionToReplace, typeReferenceToReplace; List replacement; Position position; static ReplacementOrder forIdentifier(String identifier, String newValue, Position position) { ReplacementOrder order = new ReplacementOrder(); order.identifierToReplace = identifier; order.replacement = Collections.singletonList(newValue == null ? null : Identifier.of(newValue)); order.position = position; return order; } static ReplacementOrder forStatement(String label, List replacements, Position position) { ReplacementOrder order = new ReplacementOrder(); order.statementToReplace = label; order.replacement = replacements == null ? Collections.emptyList() : replacements; order.position = position; return order; } static ReplacementOrder forExpression(String identifier, Node replacement, Position position) { ReplacementOrder order = new ReplacementOrder(); order.expressionToReplace = identifier; order.replacement = Collections.singletonList(replacement); order.position = position; return order; } static ReplacementOrder forTypeReference(String identifier, Node replacement, Position position) { ReplacementOrder order = new ReplacementOrder(); order.typeReferenceToReplace = identifier; order.replacement = Collections.singletonList(replacement); order.position = position; return order; } } private final AstVisitor visitor = new ForwardingAstVisitor() { @Override public boolean visitNode(Node node) { node.setPosition(new Position(location, location, responsible)); return false; } @Override public void endVisit(Node node) { node.setPosition(new Position(node.getPosition().getStart(), location, responsible)); } private ReplacementOrder currentOrder() { return (replacementsPointer < replacements.size()) ? replacements.get(replacementsPointer) : null; } @Override public boolean visitIdentifier(Identifier node) { ReplacementOrder order = currentOrder(); if (order != null && order.identifierToReplace != null) { if (order.identifierToReplace.equals(node.astValue())) { Node replacement = order.replacement.get(0); int startLoc = order.position == null ? location : order.position.getStart(); int endLoc = order.position == null ? location : order.position.getEnd(); replacement.setPosition(new Position(startLoc, endLoc, responsible)); location = endLoc; node.replace(replacement); replacementsPointer++; return true; } } return visitNode(node); } @Override public boolean visitLabelledStatement(LabelledStatement node) { ReplacementOrder order = currentOrder(); if (order != null && order.statementToReplace.equals(node.astLabel().astValue())) { if (!(node.rawStatement() instanceof EmptyStatement)) { throw new IllegalStateException("Placeholder statements in templates should be of the form: \"labelName: ;\" - i.e. a labelled empty statement"); } int startLoc, endLoc; if (order.position == null) { if (order.replacement.isEmpty() || order.replacement.get(0).getPosition().getStart() < 0) startLoc = location; else startLoc = order.replacement.get(0).getPosition().getStart(); if (order.replacement.isEmpty() || order.replacement.get(order.replacement.size() - 1).getPosition().getEnd() < 0) endLoc = location; else endLoc = order.replacement.get(order.replacement.size() - 1).getPosition().getEnd(); } else { startLoc = order.position.getStart(); endLoc = order.position.getEnd(); } switch (order.replacement.size()) { case 0: node.unparent(); break; case 1: Node replacement = order.replacement.get(0); if (replacement.getPosition().isUnplaced()) Ast.setAllPositions(replacement, new Position(startLoc, endLoc, responsible)); node.replace(replacement); break; default: // Replacing multiple statements only works in a Block. Block b = node.upToBlock(); if (b == null) throw new IllegalStateException("Replacing one placeholder statement with multiple statements is legal only if the placeholder is in a block"); b.rawContents().addAfter(node, order.replacement.toArray(new Node[0])); node.unparent(); for (Node n : order.replacement) { if (n.getPosition().isUnplaced()) Ast.setAllPositions(n, new Position(startLoc, endLoc, responsible)); } } replacementsPointer++; location = endLoc; return true; } return visitNode(node); } @Override public boolean visitVariableReference(VariableReference node) { ReplacementOrder order = currentOrder(); if (order != null && order.expressionToReplace.equals(node.astIdentifier().astValue())) { Node replacement = order.replacement.get(0); int startLoc, endLoc; if (order.position == null) { if (order.replacement.isEmpty() || replacement.getPosition().getStart() < 0) startLoc = location; else startLoc = replacement.getPosition().getStart(); if (order.replacement.isEmpty() || replacement.getPosition().getEnd() < 0) endLoc = location; else endLoc = replacement.getPosition().getEnd(); } else { startLoc = order.position.getStart(); endLoc = order.position.getEnd(); } if (replacement.getPosition().isUnplaced()) Ast.setAllPositions(replacement, new Position(startLoc, endLoc, responsible)); location = endLoc; node.replace(replacement); replacementsPointer++; return true; } return visitNode(node); } @Override public boolean visitTypeReference(TypeReference node) { ReplacementOrder order = currentOrder(); if (order != null && node.astParts().size() == 1 && node.astParts().last().rawTypeArguments().isEmpty() && node.astParts().last().astIdentifier().astValue().equals(order.typeReferenceToReplace)) { Node replacement = order.replacement.get(0); int startLoc, endLoc; if (order.position == null) { if (order.replacement.isEmpty() || replacement.getPosition().getStart() < 0) startLoc = location; else startLoc = replacement.getPosition().getStart(); if (order.replacement.isEmpty() || replacement.getPosition().getEnd() < 0) endLoc = location; else endLoc = replacement.getPosition().getEnd(); } else { startLoc = order.position.getStart(); endLoc = order.position.getEnd(); } if (replacement.getPosition().isUnplaced()) Ast.setAllPositions(replacement, new Position(startLoc, endLoc, responsible)); location = endLoc; node.replace(replacement); replacementsPointer++; return true; } return visitNode(node); } }; private Template(T node) { this.node = node; } public Template setStartPosition(int location) { this.location = location; return this; } public Template setResponsibleNode(Node responsible) { this.responsible = responsible; return this; } public Template replaceIdentifier(String placeholder, String replacement, Position p) { this.replacements.add(ReplacementOrder.forIdentifier(placeholder, replacement, p)); return this; } public Template replaceIdentifier(String placeholder, String replacement) { return replaceIdentifier(placeholder, replacement, null); } public Template replaceStatement(String placeholder, Node replacement, Position p) { this.replacements.add(ReplacementOrder.forStatement(placeholder, replacement == null ? Collections.emptyList() : Collections.singletonList(replacement), p)); return this; } public Template replaceStatement(String placeholder, Node replacement) { return replaceStatement(placeholder, replacement, null); } public Template replaceStatement(String placeholder, List replacement, Position p) { this.replacements.add(ReplacementOrder.forStatement(placeholder, replacement, p)); return this; } public Template replaceStatement(String placeholder, List replacement) { return replaceStatement(placeholder, replacement, null); } public Template replaceExpression(String placeholder, Node replacement, Position p) { this.replacements.add(ReplacementOrder.forExpression(placeholder, replacement, p)); return this; } public Template replaceExpression(String placeholder, Node replacement) { return replaceExpression(placeholder, replacement, null); } public Template replaceTypeReference(String placeholder, Node replacement, Position p) { this.replacements.add(ReplacementOrder.forTypeReference(placeholder, replacement, p)); return this; } public Template replaceTypeReference(String placeholder, Node replacement) { return replaceTypeReference(placeholder, replacement, null); } public T finish() { node.accept(visitor); return node; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy