mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 16:58:56 +00:00
NEW - bug 251861: [Core] Partial parsing does not work in case of appending text
https://bugs.eclipse.org/bugs/show_bug.cgi?id=251861
This commit is contained in:
parent
191481e84c
commit
3a30307849
2 changed files with 45 additions and 25 deletions
|
@ -12,6 +12,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.eclipse.emf.common.util.EList;
|
||||
import org.eclipse.emf.ecore.EClass;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
|
@ -33,17 +34,23 @@ import org.eclipse.xtext.util.StringInputStream;
|
|||
*/
|
||||
public class PartialParsingUtil {
|
||||
|
||||
private static final Logger log = Logger.getLogger(PartialParsingUtil.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static IParseResult reparse(IParser parser, CompositeNode rootNode, int originalOffset, int originalLength,
|
||||
String changedRegion) {
|
||||
PartialParsingPointers parsingPointers = calculatePartialParsingPointers(rootNode, originalOffset,
|
||||
originalLength);
|
||||
public static IParseResult reparse(IParser parser, CompositeNode rootNode, int offset, int replacedTextLength,
|
||||
String newText) {
|
||||
if (offset + replacedTextLength > rootNode.getLength()) {
|
||||
log.error("Invalid replace region offset=" + offset + " length=" + replacedTextLength + " originalLength="
|
||||
+ rootNode.getLength());
|
||||
return fullyReparse(parser, rootNode, offset, replacedTextLength, newText);
|
||||
}
|
||||
PartialParsingPointers parsingPointers = calculatePartialParsingPointers(rootNode, offset, replacedTextLength);
|
||||
List<CompositeNode> validReplaceRootNodes = parsingPointers.getValidReplaceRootNodes();
|
||||
CompositeNode replaceNode = null;
|
||||
String reparseRegion = "";
|
||||
for (int i = validReplaceRootNodes.size() - 1; i >= 0; --i) {
|
||||
replaceNode = validReplaceRootNodes.get(i);
|
||||
reparseRegion = insertChangeIntoReplaceRegion(replaceNode, originalOffset, originalLength, changedRegion);
|
||||
reparseRegion = insertChangeIntoReplaceRegion(replaceNode, offset, replacedTextLength, newText);
|
||||
if (!"".equals(reparseRegion)) {
|
||||
break;
|
||||
}
|
||||
|
@ -64,8 +71,7 @@ public class PartialParsingUtil {
|
|||
}
|
||||
if (parseResult == null || parseResult.getParseErrors() != null && !parseResult.getParseErrors().isEmpty()) {
|
||||
// on error fully reparse
|
||||
reparseRegion = insertChangeIntoReplaceRegion(rootNode, originalOffset, originalLength, changedRegion);
|
||||
return parser.parse(new StringInputStream(reparseRegion));
|
||||
return fullyReparse(parser, rootNode, offset, replacedTextLength, newText);
|
||||
}
|
||||
if (replaceNode != rootNode) {
|
||||
CompositeNode replaceNodeParent = replaceNode.getParent();
|
||||
|
@ -93,30 +99,46 @@ public class PartialParsingUtil {
|
|||
return parseResult;
|
||||
}
|
||||
|
||||
private static IParseResult fullyReparse(IParser parser, CompositeNode rootNode, int offset,
|
||||
int replacedTextLength, String newText) {
|
||||
String reparseRegion;
|
||||
reparseRegion = insertChangeIntoReplaceRegion(rootNode, offset, replacedTextLength, newText);
|
||||
return parser.parse(new StringInputStream(reparseRegion));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param replaceRootNode
|
||||
* @param originalOffset
|
||||
* @param originalLength
|
||||
* @param offset
|
||||
* @param replacedTextLength
|
||||
*/
|
||||
public static String insertChangeIntoReplaceRegion(CompositeNode replaceRootNode, int originalOffset,
|
||||
int originalLength, String changedRegion) {
|
||||
public static String insertChangeIntoReplaceRegion(CompositeNode replaceRootNode, int offset,
|
||||
int replacedTextLength, String newText) {
|
||||
String originalRegion = replaceRootNode.serialize();
|
||||
int changeOffset = originalOffset - replaceRootNode.getOffset();
|
||||
int changeOffset = offset - replaceRootNode.getOffset();
|
||||
StringBuffer reparseRegion = new StringBuffer();
|
||||
reparseRegion.append(originalRegion.substring(0, changeOffset));
|
||||
reparseRegion.append(changedRegion);
|
||||
reparseRegion.append(originalRegion.substring(changeOffset + originalLength));
|
||||
reparseRegion.append(newText);
|
||||
// TODO: rausragende region
|
||||
reparseRegion.append(originalRegion.substring(changeOffset + replacedTextLength));
|
||||
return reparseRegion.toString();
|
||||
}
|
||||
|
||||
public static PartialParsingPointers calculatePartialParsingPointers(CompositeNode rootNode, int offset, int length) {
|
||||
List<CompositeNode> nodesEnclosingRegion = collectNodesEnclosingChangeRegion(rootNode, offset, length);
|
||||
public static PartialParsingPointers calculatePartialParsingPointers(CompositeNode rootNode, int offset,
|
||||
int replacedTextLength) {
|
||||
if (offset == rootNode.getLength() && offset != 0) {
|
||||
// newText is appended, so look for the last original character instead
|
||||
--offset;
|
||||
replacedTextLength = 1;
|
||||
}
|
||||
List<CompositeNode> nodesEnclosingRegion = collectNodesEnclosingChangeRegion(rootNode, offset,
|
||||
replacedTextLength);
|
||||
List<CompositeNode> validReplaceRootNodes = internalFindValidReplaceRootNodeForChangeRegion(
|
||||
nodesEnclosingRegion, offset, length);
|
||||
nodesEnclosingRegion, offset, replacedTextLength);
|
||||
if (validReplaceRootNodes.isEmpty()) {
|
||||
validReplaceRootNodes = Collections.<CompositeNode> singletonList(rootNode);
|
||||
}
|
||||
return new PartialParsingPointers(rootNode, offset, length, validReplaceRootNodes, nodesEnclosingRegion);
|
||||
return new PartialParsingPointers(rootNode, offset, replacedTextLength, validReplaceRootNodes,
|
||||
nodesEnclosingRegion);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,8 +209,7 @@ public class PartialParsingUtil {
|
|||
if (nodeIsBeforeRegion(lastLookaheadLeafNode, offset)) {
|
||||
// last lookahead token is before changed region
|
||||
// and parent has consumed all current lookahead tokens
|
||||
NodeUtil.dumpCompositeNodeInfo("Possible entry node: "
|
||||
, node);
|
||||
NodeUtil.dumpCompositeNodeInfo("Possible entry node: ", node);
|
||||
validReplaceRootNodes.add(node);
|
||||
lookaheadChanged = false;
|
||||
}
|
||||
|
|
|
@ -38,9 +38,8 @@ public class PartialParsingPointerTest extends AbstractPartialParserTest {
|
|||
parsingPointers = calculatePartialParsingPointers(model, 1, 1);
|
||||
checkParseRegionPointers(parsingPointers, "(a+b+c)", "Parens", "Parens", "Op", "Op", "values");
|
||||
|
||||
//TODO repair
|
||||
// parsingPointers = calculatePartialParsingPointers(model, 3, 1);
|
||||
// checkParseRegionPointers(parsingPointers, "b", "Multiplication", "Multiplication", "Atom", "Op", "values");
|
||||
parsingPointers = calculatePartialParsingPointers(model, 3, 1);
|
||||
checkParseRegionPointers(parsingPointers, "b", "Multiplication", "Multiplication", "Atom", "Op", "values");
|
||||
|
||||
parsingPointers = calculatePartialParsingPointers(model, 5, 2);
|
||||
checkParseRegionPointers(parsingPointers, "(a+b+c)", "Parens", "Parens", "Op", "Op", "values");
|
||||
|
@ -48,8 +47,8 @@ public class PartialParsingPointerTest extends AbstractPartialParserTest {
|
|||
parsingPointers = calculatePartialParsingPointers(model, 6, 1);
|
||||
checkParseRegionPointers(parsingPointers, "(a+b+c)", "Parens", "Parens", "Op", "Op", "values");
|
||||
|
||||
// parsingPointers = calculatePartialParsingPointers(model, 8, 2);
|
||||
// checkParseRegionPointers(parsingPointers, "(c/d)", "Term", "Term", "Op", "Op", "values");
|
||||
parsingPointers = calculatePartialParsingPointers(model, 8, 2);
|
||||
checkParseRegionPointers(parsingPointers, "(c/d)", "Term", "Term", "Op", "Op", "values");
|
||||
|
||||
parsingPointers = calculatePartialParsingPointers(model, 9, 2);
|
||||
checkParseRegionPointers(parsingPointers, "(c/d)", "Parens", "Parens", "Op", "Op", "values");
|
||||
|
|
Loading…
Reference in a new issue