/*******************************************************************************
* Copyright (c) 2012-2015 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.jdt.javaeditor;
import com.google.inject.Singleton;
import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.che.ide.ext.java.shared.dto.HighlightedPosition;
import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.BooleanLiteral;
import org.eclipse.jdt.core.dom.CharacterLiteral;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.NumberLiteral;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import java.util.ArrayList;
import java.util.List;
/**
* Semantic highlighting reconciler
*
* @author Evgen Vidolob
*/
@Singleton
public class SemanticHighlightingReconciler {
/**
* Semantic highlightings
*/
private SemanticHighlighting[] fJobSemanticHighlightings;
/** Background job's added highlighted positions */
private ThreadLocal<List<HighlightedPosition>> fAddedPositions = new ThreadLocal<>();
private SemanticHighlighting fJobDeprecatedMemberHighlighting;
public SemanticHighlightingReconciler() {
fJobSemanticHighlightings = SemanticHighlightings.getSemanticHighlightings();
for (SemanticHighlighting highlighting : fJobSemanticHighlightings) {
if (highlighting instanceof SemanticHighlightings.DeprecatedMemberHighlighting) {
fJobDeprecatedMemberHighlighting = highlighting;
break;
}
}
}
public List<HighlightedPosition> reconcileSemanticHighlight(CompilationUnit ast) {
fAddedPositions.set(new ArrayList<HighlightedPosition>());
PositionCollector collector = new PositionCollector();
ast.accept(collector);
return fAddedPositions.get();
}
/**
* Collects positions from the AST.
*/
private class PositionCollector extends GenericVisitor {
/** The semantic token */
private SemanticToken fToken = new SemanticToken();
/*
* @see org.eclipse.jdt.internal.corext.dom.GenericVisitor#visitNode(org.eclipse.jdt.core.dom.ASTNode)
*/
@Override
protected boolean visitNode(ASTNode node) {
if ((node.getFlags() & ASTNode.MALFORMED) == ASTNode.MALFORMED) {
// retainPositions(node.getStartPosition(), node.getLength());
return false;
}
return true;
}
/*
* @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BooleanLiteral)
*/
@Override
public boolean visit(BooleanLiteral node) {
return visitLiteral(node);
}
/*
* @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CharacterLiteral)
*/
@Override
public boolean visit(CharacterLiteral node) {
return visitLiteral(node);
}
/*
* @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NumberLiteral)
*/
@Override
public boolean visit(NumberLiteral node) {
return visitLiteral(node);
}
private boolean visitLiteral(Expression node) {
fToken.update(node);
for (int i = 0, n = fJobSemanticHighlightings.length; i < n; i++) {
SemanticHighlighting semanticHighlighting = fJobSemanticHighlightings[i];
if (semanticHighlighting.consumesLiteral(fToken)) {
int offset = node.getStartPosition();
int length = node.getLength();
if (offset > -1 && length > 0)
addPosition(offset, length, semanticHighlighting);
break;
}
}
fToken.clear();
return false;
}
/*
* @see org.eclipse.jdt.internal.corext.dom.GenericVisitor#visit(org.eclipse.jdt.core.dom.ConstructorInvocation)
* @since 3.5
*/
@Override
public boolean visit(ConstructorInvocation node) {
// XXX Hack for performance reasons (should loop over fJobSemanticHighlightings can call consumes(*))
if (fJobDeprecatedMemberHighlighting != null) {
IMethodBinding constructorBinding = node.resolveConstructorBinding();
if (constructorBinding != null && constructorBinding.isDeprecated()) {
int offset = node.getStartPosition();
int length = 4;
if (offset > -1 && length > 0)
addPosition(offset, length, fJobDeprecatedMemberHighlighting);
}
}
return true;
}
/*
* @see org.eclipse.jdt.internal.corext.dom.GenericVisitor#visit(org.eclipse.jdt.core.dom.ConstructorInvocation)
* @since 3.5
*/
@Override
public boolean visit(SuperConstructorInvocation node) {
// XXX Hack for performance reasons (should loop over fJobSemanticHighlightings can call consumes(*))
if (fJobDeprecatedMemberHighlighting != null) {
IMethodBinding constructorBinding = node.resolveConstructorBinding();
if (constructorBinding != null && constructorBinding.isDeprecated()) {
int offset = node.getStartPosition();
int length = 5;
if (offset > -1 && length > 0)
addPosition(offset, length, fJobDeprecatedMemberHighlighting);
}
}
return true;
}
/*
* @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SimpleName)
*/
@Override
public boolean visit(SimpleName node) {
fToken.update(node);
for (int i = 0, n = fJobSemanticHighlightings.length; i < n; i++) {
SemanticHighlighting semanticHighlighting = fJobSemanticHighlightings[i];
if (semanticHighlighting.consumes(fToken)) {
int offset = node.getStartPosition();
int length = node.getLength();
if (offset > -1 && length > 0)
addPosition(offset, length, semanticHighlighting);
break;
}
}
fToken.clear();
return false;
}
/**
* Add a position with the given range and highlighting iff it does not exist already.
*
* @param offset
* The range offset
* @param length
* The range length
* @param highlighting
* The highlighting
*/
private void addPosition(int offset, int length, SemanticHighlighting highlighting) {
HighlightedPosition highlightedPosition = DtoFactory.getInstance().createDto(HighlightedPosition.class);
highlightedPosition.setLength(length);
highlightedPosition.setOffset(offset);
highlightedPosition.setType(highlighting.getType());
fAddedPositions.get().add(highlightedPosition);
}
}
}