/**
* <copyright>
* </copyright>
*
*
*/
package org.reuseware.air.language.abstractsyntax.resource.as.ui;
/**
* This class finds the positions to highlight and adds them to the document.
*/
public class AsOccurrence {
private final static org.reuseware.air.language.abstractsyntax.resource.as.ui.AsPositionHelper positionHelper = new org.reuseware.air.language.abstractsyntax.resource.as.ui.AsPositionHelper();
private org.reuseware.air.language.abstractsyntax.resource.as.ui.AsTokenScanner tokenScanner;
private java.util.List<String> quotedTokenArray;
private org.eclipse.jface.text.source.projection.ProjectionViewer projectionViewer;
private org.reuseware.air.language.abstractsyntax.resource.as.IAsTextResource textResource;
private String tokenText = "";
private org.eclipse.jface.text.Region tokenRegion;
private boolean isPositionsChanged = true;
/**
* Creates the Occurrence class to find position to highlight.
*
* @param textResource the text resource for location
* @param sourceViewer the source viewer for the text
* @param tokenScanner the token scanner helps to find the searched tokens
*/
public AsOccurrence(org.reuseware.air.language.abstractsyntax.resource.as.IAsTextResource textResource, org.eclipse.jface.text.source.projection.ProjectionViewer sourceViewer, org.reuseware.air.language.abstractsyntax.resource.as.ui.AsTokenScanner tokenScanner) {
this.textResource = textResource;
this.projectionViewer = sourceViewer;
quotedTokenArray = new java.util.ArrayList<String>();
String[] tokenNames = new org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsMetaInformation().getTokenNames();
for (String tokenName : tokenNames) {
if (tokenName.startsWith("'") && tokenName.endsWith("'")) {
quotedTokenArray.add(tokenName.substring(1, tokenName.length() - 1).trim());
}
}
this.tokenScanner = tokenScanner;
tokenRegion = new org.eclipse.jface.text.Region(-1, 0);
}
private org.eclipse.emf.ecore.EObject getResolvedEObject(org.eclipse.emf.ecore.EObject eObject) {
return eObject.eIsProxy() ? org.eclipse.emf.ecore.util.EcoreUtil.resolve(eObject, textResource) : eObject;
}
/**
* Tries to resolve the first proxy object in a list.
*
* @param objects the <code>EObject</code>s at the text caret
*
* @return the resolved <code>EObject</code> of the first proxy
* <code>EObject</code> in a list. If there are none returns <code>null</code>
*/
public org.eclipse.emf.ecore.EObject tryToResolve(java.util.List<org.eclipse.emf.ecore.EObject> objects) {
for (org.eclipse.emf.ecore.EObject object : objects) {
if (object.eIsProxy()) {
return getResolvedEObject(object);
}
}
return null;
}
/**
*
* @return the eObject at the current cursor position.
*/
public org.eclipse.emf.ecore.EObject getEObjectAtCurrentPosition() {
org.eclipse.swt.custom.StyledText textWidget = projectionViewer.getTextWidget();
if (textWidget == null) {
return null;
}
int caretOffset = textWidget.getCaretOffset();
caretOffset = projectionViewer.widgetOffset2ModelOffset(caretOffset);
org.reuseware.air.language.abstractsyntax.resource.as.IAsLocationMap locationMap = textResource.getLocationMap();
java.util.List<org.eclipse.emf.ecore.EObject> elementsAtOffset = locationMap.getElementsAt(caretOffset);
if (elementsAtOffset == null || elementsAtOffset.isEmpty()) {
return null;
}
for (org.eclipse.emf.ecore.EObject candidate : elementsAtOffset) {
if (candidate.eIsProxy()) {
candidate = getResolvedEObject(candidate);
}
// take an element that is actually contained in a resource. the location map
// might reference elements that were removed by a post processor
if (candidate.eResource() != null) {
return candidate;
}
}
return null;
}
/**
* Returns the token text at the caret.
*
* @return the token text
*/
public String getTokenText() {
return tokenText;
}
private int getLength(org.eclipse.emf.ecore.EObject eObject) {
org.reuseware.air.language.abstractsyntax.resource.as.IAsLocationMap locationMap = textResource.getLocationMap();
return locationMap.getCharEnd(eObject) - locationMap.getCharStart(eObject) + 1;
}
/**
* Finds the positions of the occurrences which will be highlighted. The brackets
* and the key words should not be highlighted.
*
* @param bracketSet the set of brackets which have to be ignored.
*/
public void handleOccurrenceHighlighting(org.reuseware.air.language.abstractsyntax.resource.as.ui.AsBracketSet bracketSet) {
if (textResource == null) {
return;
}
org.eclipse.swt.custom.StyledText textWidget = projectionViewer.getTextWidget();
int caretOffset = textWidget.getCaretOffset();
caretOffset = projectionViewer.widgetOffset2ModelOffset(caretOffset);
org.eclipse.jface.text.IDocument document = projectionViewer.getDocument();
if (caretOffset < 0 || caretOffset >= document.getLength()) {
return;
}
int tokenRegionOffset = tokenRegion.getOffset();
if (caretOffset >= tokenRegionOffset && caretOffset <= tokenRegionOffset + tokenRegion.getLength()) {
isPositionsChanged = false;
return;
}
tokenRegion = new org.eclipse.jface.text.Region(-1,0);
org.reuseware.air.language.abstractsyntax.resource.as.IAsLocationMap locationMap = textResource.getLocationMap();
java.util.List<org.eclipse.emf.ecore.EObject> elementsAtOffset = locationMap.getElementsAt(caretOffset);
if (elementsAtOffset == null || elementsAtOffset.size() < 1) {
return;
}
org.eclipse.emf.ecore.EObject firstElementAtOffset = elementsAtOffset.get(0);
org.eclipse.emf.ecore.EObject resolvedEO = tryToResolve(elementsAtOffset);
if (resolvedEO != null) {
elementsAtOffset = locationMap.getElementsAt(locationMap.getCharStart(resolvedEO));
}
tokenScanner.setRange(document, locationMap.getCharStart(firstElementAtOffset), getLength(firstElementAtOffset));
org.eclipse.jface.text.rules.IToken token = tokenScanner.nextToken();
while (!token.isEOF()) {
int tokenOffset = tokenScanner.getTokenOffset();
int tokenLength = tokenScanner.getTokenLength();
String text = tokenScanner.getTokenText();
if (tokenOffset <= caretOffset && tokenLength + tokenOffset > caretOffset) {
if (text.trim().equals("")) {
// the rejected elements
return;
}
tokenText = text;
tokenRegion = new org.eclipse.jface.text.Region(tokenOffset, tokenLength);
isPositionsChanged = true;
break;
}
token = tokenScanner.nextToken();
}
if (tokenText == null || tokenText.equals("")) {
return;
}
if ((resolvedEO == null && quotedTokenArray.contains(tokenText)) || (resolvedEO == null && elementsAtOffset.get(0).eResource() == null) || bracketSet.isBracket(tokenText)) {
tokenText = "";
return;
}
try {
setHighlightingPositions(resolvedEO, elementsAtOffset);
} catch (Exception e) {
e.printStackTrace();
}
}
private void setHighlightingPositions(org.eclipse.emf.ecore.EObject definitionElement, java.util.List<org.eclipse.emf.ecore.EObject> elementsAtDefinition) {
org.eclipse.jface.text.IDocument document = projectionViewer.getDocument();
org.reuseware.air.language.abstractsyntax.resource.as.IAsLocationMap locationMap = textResource.getLocationMap();
org.eclipse.jface.text.rules.IToken token;
int defPosition = -1;
boolean isNull = definitionElement == null;
if (isNull) {
definitionElement = elementsAtDefinition.get(0);
}
org.eclipse.emf.ecore.resource.Resource resource = definitionElement.eResource();
if (resource == null) {
return;
}
if (resource.equals(textResource)) {
tokenScanner.setRange(projectionViewer.getDocument(), locationMap.getCharStart(definitionElement), getLength(definitionElement));
token = tokenScanner.nextToken();
while (!token.isEOF()) {
String text = tokenScanner.getTokenText();
if (text.equals(tokenText)) {
defPosition = tokenScanner.getTokenOffset();
addPosition(document, org.reuseware.air.language.abstractsyntax.resource.as.ui.AsPositionCategory.DEFINTION.toString());
break;
}
token = tokenScanner.nextToken();
}
}
tokenScanner.setRange(projectionViewer.getDocument(), 0, projectionViewer.getDocument().getLength());
org.eclipse.emf.ecore.EObject occEO;
token = tokenScanner.nextToken();
while (!token.isEOF()) {
String text = tokenScanner.getTokenText();
if (text != null && text.equals(tokenText) && tokenScanner.getTokenOffset() != defPosition) {
occEO = tryToResolve(locationMap.getElementsAt(tokenScanner.getTokenOffset()));
if (occEO != null) {
if ((isNull && elementsAtDefinition.contains(occEO)) || !isNull && definitionElement.equals(occEO)) {
addPosition(document, org.reuseware.air.language.abstractsyntax.resource.as.ui.AsPositionCategory.PROXY.toString());
}
}
}
token = tokenScanner.nextToken();
}
}
private void addPosition(org.eclipse.jface.text.IDocument document, String positionCategory) {
int tokenOffset = tokenScanner.getTokenOffset();
int tokenLength = tokenScanner.getTokenLength();
positionHelper.addPosition(document, positionCategory, tokenOffset, tokenLength);
}
/**
* Check whether it is time to remove the occurrence highlighting.
*
* @return <code>true</code> if the caret changed the token.
*/
public boolean isToRemoveHighlighting() {
org.eclipse.swt.custom.StyledText textWidget = projectionViewer.getTextWidget();
int caretOffset = textWidget.getCaretOffset();
caretOffset = projectionViewer.widgetOffset2ModelOffset(caretOffset);
if (caretOffset >= tokenRegion.getOffset() && caretOffset <= tokenRegion.getOffset() + tokenRegion.getLength()) {
return false;
}
return true;
}
/**
* Check whether the token region changed to decide to highlight or not.
*
* @return <code>true</code> if the occurrences should be highlighted
*/
public boolean isPositionsChanged() {
return isPositionsChanged;
}
/**
* Resets the token region to enable remove highlighting if the text is changing.
*/
public void resetTokenRegion(){
tokenRegion = new org.eclipse.jface.text.Region(-1, 0);
}
}