/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.ui.editors.sql.syntax;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.jkiss.dbeaver.model.sql.SQLDialect;
import org.jkiss.dbeaver.model.sql.SQLSyntaxManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* Used to scan and detect for SQL keywords.
*/
public class SQLWordPartDetector extends SQLIdentifierDetector
{
private String prevKeyWord = "";
private String prevDelimiter = null;
private List<String> prevWords = null;
private String wordPart;
private String fullWord;
private int cursorOffset;
private int startOffset;
private int endOffset;
private int delimiterOffset;
/**
* Method SQLWordPartDetector.
*
* @param document text document
* @param syntaxManager syntax manager
* @param documentOffset into the SQL document
*/
public SQLWordPartDetector(IDocument document, SQLSyntaxManager syntaxManager, int documentOffset)
{
super(syntaxManager.getStructSeparator(), syntaxManager.getQuoteSymbol());
cursorOffset = documentOffset;
startOffset = documentOffset - 1;
endOffset = documentOffset;
int topIndex = 0, documentLength = document.getLength();
try {
boolean inQuote = false;
while (startOffset >= topIndex) {
char c = document.getChar(startOffset);
if (inQuote) {
startOffset--;
// Opening quote
if (isQuote(c)) {
break;
}
} else if (isQuote(c)) {
startOffset--;
inQuote = true;
} else if (isWordPart(c)) {
startOffset--;
} else {
break;
}
}
while (endOffset < documentLength && isWordPart(document.getChar(endOffset))) {
endOffset++;
}
int prevOffset = startOffset;
//we've been one step too far : increase the offset
startOffset++;
wordPart = document.get(startOffset, documentOffset - startOffset);
fullWord = document.get(startOffset, endOffset - startOffset);
// Get previous keyword
while (prevOffset >= topIndex) {
StringBuilder prevPiece = new StringBuilder();
while (prevOffset >= topIndex) {
char ch = document.getChar(prevOffset);
if (isWordPart(ch)) {
break;
} else if (!Character.isWhitespace(ch)) {
delimiterOffset = prevOffset;
}
prevPiece.append(ch);
prevOffset--;
}
if (prevDelimiter == null) {
//startOffset - prevPiece.length();
prevDelimiter = prevPiece.toString().trim();
}
for (String delim : syntaxManager.getStatementDelimiters()) {
if (prevPiece.indexOf(delim) != -1) {
// Statement delimiter found - do not process to previous keyword
return;
}
}
int prevStartOffset = prevOffset + 1;
while (prevOffset >= topIndex) {
char ch = document.getChar(prevOffset);
if (isWordPart(ch)) {
prevOffset--;
} else {
prevOffset++;
break;
}
}
if (prevOffset < topIndex) {
prevOffset = topIndex;
}
String prevWord = document.get(prevOffset, prevStartOffset - prevOffset);
SQLDialect dialect = syntaxManager.getDialect();
if (dialect.isEntityQueryWord(prevWord) || dialect.isAttributeQueryWord(prevWord)) {
this.prevKeyWord = prevWord.toUpperCase(Locale.ENGLISH);
break;
}
if (prevWords == null) {
prevWords = new ArrayList<>();
}
prevWords.add(prevWord);
prevOffset--;
}
} catch (BadLocationException e) {
// do nothing
}
}
/**
* Method getWordPart.
*
* @return String
*/
public String getWordPart()
{
return wordPart;
}
public String getFullWord()
{
return fullWord;
}
public String getPrevDelimiter()
{
return prevDelimiter;
}
public List<String> getPrevWords()
{
return prevWords;
}
public int getCursorOffset()
{
return cursorOffset;
}
public int getStartOffset()
{
return startOffset;
}
public int getEndOffset()
{
return endOffset;
}
public int getLength()
{
return endOffset - startOffset;
}
/**
* Previous valuable entity or attribute manipulation keyword.
* All functions, aggregate operators and other keywords are ignored.
*/
public String getPrevKeyWord()
{
return prevKeyWord;
}
public List<String> splitWordPart()
{
return super.splitIdentifier(wordPart);
}
public void moveToDelimiter() {
int shift = startOffset - delimiterOffset;
startOffset -= shift;
}
}