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:
jkohnlein 2008-10-23 15:18:12 +00:00
parent 191481e84c
commit 3a30307849
2 changed files with 45 additions and 25 deletions

View file

@ -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;
}

View file

@ -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");