blob: ded5a59038206cda23264bb9d65c321cfc09a6e4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.groovy.parser.antlr4.util;
import groovy.lang.Tuple2;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.apache.groovy.parser.antlr4.GroovyParser;
import org.codehaus.groovy.ast.ASTNode;
import static groovy.lang.Tuple.tuple;
import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asBoolean;
/**
* Utilities for configuring node positions
*/
public class PositionConfigureUtils {
/**
* Sets location(lineNumber, colNumber, lastLineNumber, lastColumnNumber) for node using standard context information.
* Note: this method is implemented to be closed over ASTNode. It returns same node as it received in arguments.
*
* @param astNode Node to be modified.
* @param ctx Context from which information is obtained.
* @return Modified astNode.
*/
public static <T extends ASTNode> T configureAST(T astNode, GroovyParser.GroovyParserRuleContext ctx) {
Token start = ctx.getStart();
Token stop = ctx.getStop();
astNode.setLineNumber(start.getLine());
astNode.setColumnNumber(start.getCharPositionInLine() + 1);
configureEndPosition(astNode, stop);
return astNode;
}
public static Tuple2<Integer, Integer> endPosition(Token token) {
String stopText = token.getText();
int stopTextLength = 0;
int newLineCnt = 0;
if (null != stopText) {
stopTextLength = stopText.length();
newLineCnt = (int) StringUtils.countChar(stopText, '\n');
}
if (0 == newLineCnt) {
return tuple(token.getLine(), token.getCharPositionInLine() + 1 + token.getText().length());
} else { // e.g. GStringEnd contains newlines, we should fix the location info
return tuple(token.getLine() + newLineCnt, stopTextLength - stopText.lastIndexOf('\n'));
}
}
public static <T extends ASTNode> T configureAST(T astNode, TerminalNode terminalNode) {
return configureAST(astNode, terminalNode.getSymbol());
}
public static <T extends ASTNode> T configureAST(T astNode, Token token) {
astNode.setLineNumber(token.getLine());
astNode.setColumnNumber(token.getCharPositionInLine() + 1);
astNode.setLastLineNumber(token.getLine());
astNode.setLastColumnNumber(token.getCharPositionInLine() + 1 + token.getText().length());
return astNode;
}
public static <T extends ASTNode> T configureAST(T astNode, ASTNode source) {
astNode.setLineNumber(source.getLineNumber());
astNode.setColumnNumber(source.getColumnNumber());
astNode.setLastLineNumber(source.getLastLineNumber());
astNode.setLastColumnNumber(source.getLastColumnNumber());
return astNode;
}
public static <T extends ASTNode> T configureAST(T astNode, GroovyParser.GroovyParserRuleContext ctx, ASTNode initialStop) {
Token start = ctx.getStart();
Token stop = ctx.getStop();
astNode.setLineNumber(start.getLine());
astNode.setColumnNumber(start.getCharPositionInLine() + 1);
if (asBoolean(initialStop)) {
astNode.setLastLineNumber(initialStop.getLastLineNumber());
astNode.setLastColumnNumber(initialStop.getLastColumnNumber());
} else {
configureEndPosition(astNode, ctx.getStop());
}
return astNode;
}
public static <T extends ASTNode> void configureEndPosition(T astNode, Token token) {
Tuple2<Integer, Integer> endPosition = endPosition(token);
astNode.setLastLineNumber(endPosition.getV1());
astNode.setLastColumnNumber(endPosition.getV2());
}
public static <T extends ASTNode> T configureAST(T astNode, ASTNode start, ASTNode stop) {
astNode.setLineNumber(start.getLineNumber());
astNode.setColumnNumber(start.getColumnNumber());
if (asBoolean(stop)) {
astNode.setLastLineNumber(stop.getLastLineNumber());
astNode.setLastColumnNumber(stop.getLastColumnNumber());
} else {
astNode.setLastLineNumber(start.getLastLineNumber());
astNode.setLastColumnNumber(start.getLastColumnNumber());
}
return astNode;
}
}