Bug 2073 - On restart of WRT tools - its hard to know which project the open file is in
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.debug.ui.editors;
import java.util.regex.Pattern;
import org.chromium.debug.core.ChromiumDebugPlugin;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
/**
* A utility for handling JavaScript-related data.
*/
public class JavascriptUtil {
private static final String OPEN_BRACKET = "["; //$NON-NLS-1$
private static final String CLOSE_BRACKET = "]"; //$NON-NLS-1$
private static final String ID_CHARS_REGEX = "\\p{L}_$\\d"; //$NON-NLS-1$
private static final String QUALIFIED_ID_CHARS_REGEX = ID_CHARS_REGEX + "\\.\\[\\]"; //$NON-NLS-1$
/**
* Contains chars acceptable as part of expression to inspect to the right of
* the cursor.
*/
public static final Pattern ID_PATTERN =
Pattern.compile(OPEN_BRACKET + ID_CHARS_REGEX + CLOSE_BRACKET);
/**
* Contains chars acceptable as part of expression to inspect to the left of
* the cursor.
*/
public static final Pattern QUALIFIED_ID_PATTERN =
Pattern.compile(OPEN_BRACKET + QUALIFIED_ID_CHARS_REGEX + CLOSE_BRACKET);
public static boolean isJsIdentifierCharacter(char ch, boolean qualified) {
return qualified
? QUALIFIED_ID_PATTERN.matcher(String.valueOf(ch)).find()
: ID_PATTERN.matcher(String.valueOf(ch)).find();
}
/**
* Returns a JavaScript qualified identifier surrounding the character at
* {@code offset} position in the given {@code document}.
*
* @param document to extract an identifier from
* @param offset of the pivot character (before, in, or after the identifier)
* @return JavaScript identifier, or {@code null} if none found
*/
public static String extractSurroundingJsIdentifier(IDocument document, int offset) {
IRegion region = getSurroundingIdentifierRegion(document, offset, true);
try {
return region == null
? null
: document.get(region.getOffset(), region.getLength());
} catch (BadLocationException e) {
ChromiumDebugPlugin.log(e);
return null;
}
}
/**
* Returns a region enclosing a JavaScript identifier found in {@code doc} at
* the {@code offset} position. If {@code qualified == true}, all leading
* qualifying names will be included into the region, otherwise the member
* operator (".") will be considered as an identifier terminator.
*
* @param doc the document to extract an identifier region from
* @param offset of the pivot character (before, in, or after the identifier)
* @param qualified whether to read qualified identifiers rather than simple
* ones
* @return an IRegion corresponding to the JavaScript identifier overlapping
* offset, or null if none
*/
public static IRegion getSurroundingIdentifierRegion(
IDocument doc, int offset, boolean qualified) {
if (doc == null) {
return null;
}
try {
int squareBrackets = 0;
char ch = doc.getChar(offset);
if (!isJsIdentifierCharacter(ch, qualified) && offset > 0) {
--offset; // cursor is AFTER the identifier
}
int start = offset;
int end = offset;
int goodStart = offset;
while (start >= 0) {
ch = doc.getChar(start);
if (!isJsIdentifierCharacter(ch, qualified)) {
break;
}
if (ch == '[') {
squareBrackets--;
} else if (ch == ']') {
squareBrackets++;
}
if (squareBrackets < 0) {
break;
}
goodStart = start;
--start;
}
start = goodStart;
int length = doc.getLength();
while (end < length) {
try {
ch = doc.getChar(end);
if (!isJsIdentifierCharacter(ch, false)) {
// stop at the current name qualifier
// rather than scan through the entire qualified id
break;
}
++end;
} catch (BadLocationException e) {
ChromiumDebugPlugin.log(e);
}
}
if (start >= end) {
return null;
} else {
return new Region(start, end - start);
}
} catch (BadLocationException e) {
ChromiumDebugPlugin.log(e);
return null;
}
}
private JavascriptUtil() {
// not instantiable
}
}