* the offset for which to search the closest position
* @return the closest position in the partitioner's category
*/
private Position findMatchingTag(int offset) {
CFEPartition currentPartition = this.partitioner.findClosestPartition(offset);
if (currentPartition == null) {
return null;
}
CFEPartition[] fullStartTagPartitions = this.partitioner.getStartTagPartitions(currentPartition.getOffset());
if (currentPartition.isMidPartition() || currentPartition.isEndPartition()) {
//System.out.println("Clicked in tag attributes or by closing chevron; finding start tag");
// CFEPartition prevPartition = (CFEPartition) category[--index];
CFEPartition prevPartition = this.partitioner.getPreviousPartition(currentPartition.getOffset());
//System.out.println("Checked previous partition: " + prevPartition.getType() + "(" + prevPartition.getTagName());
while (prevPartition != null && (!prevPartition.isStartPartition())) {
// prevPartition = (CFEPartition) category[--index];
prevPartition = this.partitioner.getPreviousPartition(prevPartition.getOffset());
//System.out.println("Checked previous partition: " + prevPartition.getType() + "(" + prevPartition.getTagName());
}
//System.out.println("Found start tag!");
currentPartition = prevPartition;
}
// By this point, we have either returned null or we have the correct start or end CF Tag partition
String tagName = currentPartition.getTagName();
//System.out.println("Current tag name: " + tagName);
int stackDepth = 0;
if (currentPartition.isStartPartition()) {
//System.out.println("In start tag; looking for matching end tag");
int lastPartitionIndex = fullStartTagPartitions.length - 1;
int closingPartitionLength = fullStartTagPartitions[lastPartitionIndex].getLength();
if (closingPartitionLength == 2) {
// Self-closing tag
//System.out.println("This is a self-closing tag.");
IStatusLineManager statusLM = editor.getEditorSite().getActionBars().getStatusLineManager();
statusLM.setMessage("This is a self-closing tag.");
return null;
}
// Start after the closing chevron
CFEPartition checkMatchPartition = this.partitioner.getNextPartition(fullStartTagPartitions[lastPartitionIndex].getOffset());
while (checkMatchPartition != null) {
// System.out.println("Checked partition tag name: " + checkMatchPartition.getTagName() + " & type: " + checkMatchPartition.getType());
if (checkMatchPartition.isStartPartition() && currentPartition.getTagName().equalsIgnoreCase(checkMatchPartition.getTagName())) {
//System.out.println("Encountered nested start tag before end tag");
stackDepth++;
checkMatchPartition = this.partitioner.getNextPartition(checkMatchPartition.getOffset());
continue;
}
if (!checkMatchPartition.isCloser() || !tagName.equalsIgnoreCase(checkMatchPartition.getTagName())) {
//System.out.println("Partition at offset " + checkMatchPartition.getOffset() + " is not a closer or is a different tag");
checkMatchPartition = this.partitioner.getNextPartition(checkMatchPartition.getOffset());
continue;
}
// If we've reached this point, we should be at a closing tag with the same name
if (stackDepth > 0) {
//System.out.println("Found match for nested tag; removing from stack");
stackDepth--;
checkMatchPartition = this.partitioner.getNextPartition(checkMatchPartition.getOffset());
continue;
}
//System.out.println("Found match! Is it a start partition: " + checkMatchPartition.isStartPartition());
IStatusLineManager statusLM = editor.getEditorSite().getActionBars().getStatusLineManager();
statusLM.setMessage(null);
return checkMatchPartition;
}
//System.out.println("Looks like there's no match.");
}
else { // Trying to find the matching start tag for an end tag
CFEPartition checkMatchPartition = this.partitioner.getPreviousPartition(currentPartition.getOffset());
int start = 0;
int end = 0;
boolean matchFound = false;
while (checkMatchPartition != null) {
if (checkMatchPartition.isCloser() && currentPartition.getTagName().equalsIgnoreCase(checkMatchPartition.getTagName())) {
//System.out.println("Encountered nested end tag before start tag");
stackDepth++;
checkMatchPartition = this.partitioner.getPreviousPartition(checkMatchPartition.getOffset());
continue;
}
if (!tagName.equalsIgnoreCase(checkMatchPartition.getTagName()) || (checkMatchPartition.isMidPartition())) {
//System.out.println("Partition at offset " + checkMatchPartition.getOffset() + " doesn't match");
checkMatchPartition = this.partitioner.getPreviousPartition(checkMatchPartition.getOffset());
continue;
}
if (checkMatchPartition.isStartPartition() && currentPartition.getTagName().equals(checkMatchPartition.getTagName())) {
if (stackDepth == 0) {
//System.out.println("Found match at offset " + checkMatchPartition.getOffset());
// return checkMatchPartition;
matchFound = true;
break;
}
else {
//System.out.println("Found match for nested tag; removing from stack");
stackDepth--;
}
}
checkMatchPartition = this.partitioner.getPreviousPartition(checkMatchPartition.getOffset());
}
if (!matchFound) {
IStatusLineManager statusLM = editor.getEditorSite().getActionBars().getStatusLineManager();
statusLM.setMessage("No matching tag found.");
return null;
}
if (checkMatchPartition == null ) {
return null;
}
CFEPartition[] startPartitions = this.partitioner.getStartTagPartitions(checkMatchPartition.getOffset());
if (startPartitions == null || startPartitions.length < 2) {
return null;
}
start = startPartitions[0].getOffset();
end = startPartitions[startPartitions.length - 1].getOffset() + startPartitions[startPartitions.length - 1].getLength();