/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.editor.php.internal.ui.editor.scanner;
import java.io.IOException;
import java.io.StringReader;
import java_cup.sym;
import java_cup.runtime.Symbol;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;
import org2.eclipse.php.internal.core.PHPVersion;
import org2.eclipse.php.internal.core.ast.scanner.AstLexer;
import com.aptana.core.logging.IdeLog;
import com.aptana.editor.php.PHPEditorPlugin;
import com.aptana.editor.php.core.PHPVersionProvider;
import com.aptana.editor.php.core.ast.ASTFactory;
import com.aptana.editor.php.internal.ui.editor.PHPVersionDocumentManager;
/**
* A token scanner which returns {@link IToken}s for PHP tokens. These can later be mapped to colors.
*
* @author Shalom Gibly <sgibly@aptana.com>
*/
public class PHPTokenScanner implements IPHPTokenScanner
{
// We need that prefix for our PHP lexer
protected static final String PHP_PREFIX = "<?php\n"; //$NON-NLS-1$ // $codepro.audit.disable platformSpecificLineSeparator
private int fTokenLength;
private int fOffset;
private int origOffset;
private String fContents;
private AstLexer lexer;
private PHPVersion phpVersion;
private Symbol nextNextSymbol;
/**
* Constructs a new PHPTokenScanner with a given {@link PHPVersion}.
*
* @param phpVersion
*/
public PHPTokenScanner(PHPVersion phpVersion)
{
super();
if (phpVersion == null)
{
throw new IllegalArgumentException("A null PHP Version passed to the PHPTokenScanner"); //$NON-NLS-1$
}
this.phpVersion = phpVersion;
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
*/
public int getTokenLength()
{
return fTokenLength;
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
*/
public int getTokenOffset()
{
return fOffset;
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
*/
public IToken nextToken()
{
Symbol nextSymbol = nextNextSymbol;
try
{
nextNextSymbol = lexer.next_token();
}
catch (Exception e)
{
IdeLog.logError(PHPEditorPlugin.getDefault(), "PHP token-scanner - Error getting the next token", e); //$NON-NLS-1$
nextNextSymbol = null;
}
IToken token = createToken(nextSymbol);
fTokenLength = 0;
if (token != Token.EOF)
{
// Check for a white-space gap with the next-next-symbol (if not EOF)
int whiteSpacesGap = 0;
if (nextNextSymbol != null && nextNextSymbol.sym != sym.EOF)
{
whiteSpacesGap = nextNextSymbol.left - nextSymbol.right;
}
fTokenLength = nextSymbol.right - nextSymbol.left + whiteSpacesGap;
fOffset = origOffset + nextSymbol.left - PHP_PREFIX.length();
}
return token;
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.text.rules.ITokenScanner#setRange(org.eclipse.jface.text.IDocument, int, int)
*/
public void setRange(IDocument document, int offset, int length)
{
try
{
fContents = document.get(offset, length);
fContents = PHP_PREFIX + fContents;
phpVersion = PHPVersionDocumentManager.getPHPVersion(document);
if (phpVersion == null)
{
// Set the version to the default (5.3)
// This will happen when an external file is opened in the editor.
phpVersion = PHPVersionProvider.getDefaultPHPVersion();
}
lexer = ASTFactory.getAstLexer(phpVersion, new StringReader(fContents), true); // $codepro.audit.disable
// closeWhereCreated
// read the next token already, so we can always calculate the spaces between the
// tokens and return the right offset and length.
try
{
nextNextSymbol = lexer.next_token();
}
catch (Exception e)
{
nextNextSymbol = null;
}
}
catch (BadLocationException e)
{
IdeLog.logError(PHPEditorPlugin.getDefault(), "PHP code-scanner - Error setting the range", e); //$NON-NLS-1$
}
catch (IOException e)
{
IdeLog.logError(PHPEditorPlugin.getDefault(), "PHP code-scanner - I/O error", e); //$NON-NLS-1$
}
origOffset = offset;
}
public String getContents()
{
return fContents;
}
/**
* Creates an {@link IToken} from a {@link Symbol}
*
* @param symbol
* @return {@link IToken}
*/
private IToken createToken(Symbol symbol)
{
if (symbol == null || symbol.sym == sym.EOF)
{
return Token.EOF;
}
else
{
return new Token(symbol);
}
}
/*
* (non-Javadoc)
* @see com.aptana.editor.php.internal.ui.editor.scanner.IPHPTokenScanner#getPHPVersion()
*/
public PHPVersion getPHPVersion()
{
return phpVersion;
}
}