/*
* 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.rules;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.MultiLineRule;
import org.eclipse.jface.text.rules.Token;
import org.jkiss.dbeaver.ui.editors.sql.syntax.SQLPartitionScanner;
public class NestedMultiLineRule extends MultiLineRule
{
protected int _commentNestingDepth = 0;
public NestedMultiLineRule(String startSequence, String endSequence, IToken token)
{
super(startSequence, endSequence, token);
}
public NestedMultiLineRule(String startSequence, String endSequence, IToken token, char escapeCharacter)
{
super(startSequence, endSequence, token, escapeCharacter);
}
public NestedMultiLineRule(String startSequence, String endSequence, IToken token, char escapeCharacter,
boolean breaksOnEOF)
{
super(startSequence, endSequence, token, escapeCharacter, breaksOnEOF);
}
@Override
protected boolean endSequenceDetected(ICharacterScanner scanner)
{
int c;
//char[][] delimiters = scanner.getLegalLineDelimiters();
//boolean previousWasEscapeCharacter = false;
while ((c = scanner.read()) != ICharacterScanner.EOF)
{
if (c == fEscapeCharacter)
{
// Skip the escaped character.
scanner.read();
}
else if (fEndSequence.length > 0 && c == fEndSequence[0])
{
// Check if the specified end sequence has been found.
if (sequenceDetected(scanner, fEndSequence, true))
{
_commentNestingDepth--;
}
if (_commentNestingDepth <= 0)
{
return true;
}
}
else if (fStartSequence.length > 0 && c == fStartSequence[0])
{
// Check if the nested start sequence has been found.
if (sequenceDetected(scanner, fStartSequence, false))
{
_commentNestingDepth++;
}
}
//previousWasEscapeCharacter = (c == fEscapeCharacter);
}
if (fBreaksOnEOF)
{
return true;
}
scanner.unread();
return false;
}
@Override
protected IToken doEvaluate(ICharacterScanner scanner, boolean resume)
{
if (resume)
{
_commentNestingDepth = 0;
if (scanner instanceof SQLPartitionScanner)
{
String scanned = ((SQLPartitionScanner) scanner).getScannedPartitionString();
if (scanned != null && scanned.length() > 0)
{
String startSequence = new String(fStartSequence);
int index = 0;
while ((index = scanned.indexOf(startSequence, index)) >= 0)
{
index++;
_commentNestingDepth++;
}
//must be aware of the closing sequences
String endSequence = new String(fEndSequence);
index = 0;
while ((index = scanned.indexOf(endSequence, index)) >= 0)
{
index++;
_commentNestingDepth--;
}
}
}
if (endSequenceDetected(scanner))
{
return fToken;
}
}
else
{
int c = scanner.read();
if (c == fStartSequence[0])
{
if (sequenceDetected(scanner, fStartSequence, false))
{
_commentNestingDepth = 1;
if (endSequenceDetected(scanner))
{
return fToken;
}
}
}
}
scanner.unread();
return Token.UNDEFINED;
}
}