Copyright (c) 2000, 2019 IBM Corporation and others.
This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
which accompanies this distribution, and is available at
https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
IBM Corporation - initial API and implementation
Harry Terkelsen (het@google.com) - Bug 449262 - Allow the use of third-party Java formatters
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Harry Terkelsen (het@google.com) - Bug 449262 - Allow the use of third-party Java formatters
*******************************************************************************/
package org.eclipse.jdt.core;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
import org.eclipse.jdt.core.util.ClassFormatException;
import org.eclipse.jdt.core.util.IClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.PackageFragment;
import org.eclipse.jdt.internal.core.util.ClassFileReader;
import org.eclipse.jdt.internal.core.util.Disassembler;
import org.eclipse.jdt.internal.core.util.PublicScanner;
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
Factory for creating various compiler tools, such as scanners, parsers and compilers.
This class provides static methods only.
Since: 2.0 @noinstantiate This class is not intended to be instantiated by clients. @noextend This class is not intended to be subclassed by clients.
/**
* Factory for creating various compiler tools, such as scanners, parsers and compilers.
* <p>
* This class provides static methods only.
* </p>
*
* @since 2.0
* @noinstantiate This class is not intended to be instantiated by clients.
* @noextend This class is not intended to be subclassed by clients.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class ToolFactory {
This mode is used for formatting new code when some formatter options should not be used.
In particular, options that preserve the indentation of comments are not used.
In the future, newly added options may be ignored as well.
Clients that are formatting new code are recommended to use this mode.
See Also: - FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN.FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN
- DefaultCodeFormatterConstants.FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN
- createCodeFormatter(Map, int)
Since: 3.3
/**
* This mode is used for formatting new code when some formatter options should not be used.
* In particular, options that preserve the indentation of comments are not used.
* In the future, newly added options may be ignored as well.
* <p>Clients that are formatting new code are recommended to use this mode.
* </p>
*
* @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN
* @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN
* @see #createCodeFormatter(Map, int)
* @since 3.3
*/
// Supposed to be a non-compile time constant
public static final int M_FORMAT_NEW = Integer.valueOf(0).intValue();
This mode is used for formatting existing code when all formatter options should be used.
In particular, options that preserve the indentation of comments are used.
Clients that are formatting existing code are recommended to use this mode.
See Also: - FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN.FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN
- DefaultCodeFormatterConstants.FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN
- createCodeFormatter(Map, int)
Since: 3.3
/**
* This mode is used for formatting existing code when all formatter options should be used.
* In particular, options that preserve the indentation of comments are used.
* <p>Clients that are formatting existing code are recommended to use this mode.
* </p>
*
* @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN
* @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN
* @see #createCodeFormatter(Map, int)
* @since 3.3
*/
// Supposed to be a non-compile time constant
public static final int M_FORMAT_EXISTING = Integer.valueOf(1).intValue();
Create an instance of a code formatter. A code formatter implementation can be contributed via the
extension point "org.eclipse.jdt.core.codeFormatter". If unable to find a registered extension, the factory
will default to using the default code formatter.
See Also: Returns: an instance of a code formatter Deprecated: The extension point has been deprecated, use createCodeFormatter(Map)
instead.
/**
* Create an instance of a code formatter. A code formatter implementation can be contributed via the
* extension point "org.eclipse.jdt.core.codeFormatter". If unable to find a registered extension, the factory
* will default to using the default code formatter.
*
* @return an instance of a code formatter
* @see ICodeFormatter
* @see ToolFactory#createDefaultCodeFormatter(Map)
* @deprecated The extension point has been deprecated, use {@link #createCodeFormatter(Map)} instead.
*/
public static ICodeFormatter createCodeFormatter(){
Plugin jdtCorePlugin = JavaCore.getPlugin();
if (jdtCorePlugin == null) return null;
IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaCore.PLUGIN_ID, JavaModelManager.FORMATTER_EXTPOINT_ID);
if (extension != null) {
IExtension[] extensions = extension.getExtensions();
for(int i = 0; i < extensions.length; i++){
IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
for(int j = 0; j < configElements.length; j++){
try {
Object execExt = configElements[j].createExecutableExtension("class"); //$NON-NLS-1$
if (execExt instanceof ICodeFormatter){
// use first contribution found
return (ICodeFormatter)execExt;
}
} catch(CoreException e){
// unable to instantiate extension, will answer default formatter instead
}
}
}
}
// no proper contribution found, use default formatter
return createDefaultCodeFormatter(null);
}
Create an instance of the built-in code formatter.
The given options should at least provide the source level (JavaCore.COMPILER_SOURCE
), the compiler compliance level (JavaCore.COMPILER_COMPLIANCE
) and the target platform (JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM
). Without these options, it is not possible for the code formatter to know what kind of source it needs to format.
Note this is equivalent to createCodeFormatter(options, M_FORMAT_NEW)
. Thus some code formatter options may be ignored. See @{link M_FORMAT_NEW
for more details.
Params: - options – - the options map to use for formatting with the default code formatter. Recognized options
are documented on
JavaCore#getDefaultOptions()
. If set to null
, then use
the current settings from JavaCore#getOptions
.
See Also: Returns: an instance of the built-in code formatter Since: 3.0
/**
* Create an instance of the built-in code formatter.
* <p>The given options should at least provide the source level ({@link JavaCore#COMPILER_SOURCE}),
* the compiler compliance level ({@link JavaCore#COMPILER_COMPLIANCE}) and the target platform
* ({@link JavaCore#COMPILER_CODEGEN_TARGET_PLATFORM}).
* Without these options, it is not possible for the code formatter to know what kind of source it needs to format.
* </p><p>
* Note this is equivalent to <code>createCodeFormatter(options, M_FORMAT_NEW)</code>. Thus some code formatter options
* may be ignored. See @{link {@link #M_FORMAT_NEW} for more details.
* </p>
* @param options - the options map to use for formatting with the default code formatter. Recognized options
* are documented on <code>JavaCore#getDefaultOptions()</code>. If set to <code>null</code>, then use
* the current settings from <code>JavaCore#getOptions</code>.
* @return an instance of the built-in code formatter
* @see CodeFormatter
* @see JavaCore#getOptions()
* @since 3.0
*/
public static CodeFormatter createCodeFormatter(Map options){
return createCodeFormatter(options, M_FORMAT_NEW);
}
Creates an instance of a code formatter. A code formatter implementation can be contributed via the extension
point "org.eclipse.jdt.core.javaFormatter". The formatter id specified in the
"org.eclipse.jdt.core.javaFormatter" is instantiated. If unable to find a registered extension, the factory will
default to using the default code formatter.
The given options should at least provide the source level (JavaCore.COMPILER_SOURCE
), the compiler compliance level (JavaCore.COMPILER_COMPLIANCE
) and the target platform (JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM
). Without these options, it is not possible for the code formatter to know what kind of source it needs to format.
The given mode determines what options should be enabled when formatting the code. It can have the following values: M_FORMAT_NEW
, M_FORMAT_EXISTING
, but other values may be added in the future.
Params: - options – the options map to use for formatting with the default code formatter. Recognized options
are documented on
JavaCore#getDefaultOptions()
. If set to null
, then use
the current settings from JavaCore#getOptions
. - mode – the given mode to modify the given options.
See Also: Returns: an instance of the built-in code formatter Since: 3.3
/**
* Creates an instance of a code formatter. A code formatter implementation can be contributed via the extension
* point "org.eclipse.jdt.core.javaFormatter". The formatter id specified in the
* "org.eclipse.jdt.core.javaFormatter" is instantiated. If unable to find a registered extension, the factory will
* default to using the default code formatter.
* <p>The given options should at least provide the source level ({@link JavaCore#COMPILER_SOURCE}),
* the compiler compliance level ({@link JavaCore#COMPILER_COMPLIANCE}) and the target platform
* ({@link JavaCore#COMPILER_CODEGEN_TARGET_PLATFORM}).
* Without these options, it is not possible for the code formatter to know what kind of source it needs to format.
* </p>
* <p>The given mode determines what options should be enabled when formatting the code. It can have the following
* values: {@link #M_FORMAT_NEW}, {@link #M_FORMAT_EXISTING}, but other values may be added in the future.
* </p>
*
* @param options the options map to use for formatting with the default code formatter. Recognized options
* are documented on <code>JavaCore#getDefaultOptions()</code>. If set to <code>null</code>, then use
* the current settings from <code>JavaCore#getOptions</code>.
* @param mode the given mode to modify the given options.
*
* @return an instance of the built-in code formatter
* @see CodeFormatter
* @see JavaCore#getOptions()
* @since 3.3
*/
public static CodeFormatter createCodeFormatter(Map options, int mode) {
if (options == null) options = JavaCore.getOptions();
Map currentOptions = new HashMap(options);
if (mode == M_FORMAT_NEW) {
// disable the option for not formatting comments starting on first column
currentOptions.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_LINE_COMMENT_STARTING_ON_FIRST_COLUMN, DefaultCodeFormatterConstants.TRUE);
// disable the option for not indenting comments starting on first column
currentOptions.put(DefaultCodeFormatterConstants.FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN, DefaultCodeFormatterConstants.FALSE);
currentOptions.put(DefaultCodeFormatterConstants.FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN, DefaultCodeFormatterConstants.FALSE);
}
String formatterId = (String) options.get(JavaCore.JAVA_FORMATTER);
if (formatterId != null) {
IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaCore.PLUGIN_ID,
JavaCore.JAVA_FORMATTER_EXTENSION_POINT_ID);
if (extension != null) {
IExtension[] extensions = extension.getExtensions();
for (int i = 0; i < extensions.length; i++) {
IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
for (int j = 0; j < configElements.length; j++) {
String initializerID = configElements[j].getAttribute("id"); //$NON-NLS-1$
if (initializerID != null && initializerID.equals(formatterId)) {
try {
Object execExt = configElements[j].createExecutableExtension("class"); //$NON-NLS-1$
if (execExt instanceof CodeFormatter) {
CodeFormatter formatter = (CodeFormatter) execExt;
formatter.setOptions(currentOptions);
return formatter;
}
} catch (CoreException e) {
org.eclipse.jdt.internal.core.util.Util.log(e.getStatus());
break;
}
}
}
}
}
org.eclipse.jdt.internal.core.util.Util.log(IStatus.WARNING,
"Unable to instantiate formatter extension '" + formatterId + "', returning built-in formatter."); //$NON-NLS-1$ //$NON-NLS-2$
}
return new DefaultCodeFormatter(currentOptions);
}
Create a classfile bytecode disassembler, able to produce a String representation of a given classfile.
See Also: Returns: a classfile bytecode disassembler Since: 2.1
/**
* Create a classfile bytecode disassembler, able to produce a String representation of a given classfile.
*
* @return a classfile bytecode disassembler
* @see ClassFileBytesDisassembler
* @since 2.1
*/
public static ClassFileBytesDisassembler createDefaultClassFileBytesDisassembler(){
return new Disassembler();
}
Create a classfile bytecode disassembler, able to produce a String representation of a given classfile.
See Also: Returns: a classfile bytecode disassembler Deprecated: Use createDefaultClassFileBytesDisassembler()
instead
/**
* Create a classfile bytecode disassembler, able to produce a String representation of a given classfile.
*
* @return a classfile bytecode disassembler
* @see org.eclipse.jdt.core.util.IClassFileDisassembler
* @deprecated Use {@link #createDefaultClassFileBytesDisassembler()} instead
*/
public static org.eclipse.jdt.core.util.IClassFileDisassembler createDefaultClassFileDisassembler(){
class DeprecatedDisassembler extends Disassembler implements org.eclipse.jdt.core.util.IClassFileDisassembler {
// for backward compatibility, defines a disassembler which implements IClassFileDisassembler
}
return new DeprecatedDisassembler();
}
Create a classfile reader onto a classfile Java element.
Create a default classfile reader, able to expose the internal representation of a given classfile
according to the decoding flag used to initialize the reader.
Answer null if the file named fileName doesn't represent a valid .class file.
The decoding flags are described in IClassFileReader.
Params: - classfile – the classfile element to introspect
- decodingFlag – the flag used to decode the class file reader.
See Also: Returns: a default classfile reader
/**
* Create a classfile reader onto a classfile Java element.
* Create a default classfile reader, able to expose the internal representation of a given classfile
* according to the decoding flag used to initialize the reader.
* Answer null if the file named fileName doesn't represent a valid .class file.
*
* The decoding flags are described in IClassFileReader.
*
* @param classfile the classfile element to introspect
* @param decodingFlag the flag used to decode the class file reader.
* @return a default classfile reader
*
* @see IClassFileReader
*/
public static IClassFileReader createDefaultClassFileReader(IClassFile classfile, int decodingFlag){
IPackageFragmentRoot root = (IPackageFragmentRoot) classfile.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
if (root != null){
try {
if (root instanceof JarPackageFragmentRoot) {
String archiveName = null;
ZipFile jar = null;
try {
jar = ((JarPackageFragmentRoot)root).getJar();
archiveName = jar.getName();
} finally {
JavaModelManager.getJavaModelManager().closeZipFile(jar);
}
PackageFragment packageFragment = (PackageFragment) classfile.getParent();
String classFileName = classfile.getElementName();
String entryName = org.eclipse.jdt.internal.core.util.Util.concatWith(packageFragment.names, classFileName, '/');
return createDefaultClassFileReader(archiveName, entryName, decodingFlag);
} else {
InputStream in = null;
try {
in = ((IFile) ((JavaElement) classfile).resource()).getContents();
return createDefaultClassFileReader(in, decodingFlag);
} finally {
if (in != null)
try {
in.close();
} catch (IOException e) {
// ignore
}
}
}
} catch(CoreException e){
// unable to read
}
}
return null;
}
Create a default classfile reader, able to expose the internal representation of a given classfile
according to the decoding flag used to initialize the reader.
Answer null if the input stream contents cannot be retrieved
The decoding flags are described in IClassFileReader.
Params: - stream – the given input stream to read
- decodingFlag – the flag used to decode the class file reader.
See Also: Returns: a default classfile reader Since: 3.2
/**
* Create a default classfile reader, able to expose the internal representation of a given classfile
* according to the decoding flag used to initialize the reader.
* Answer null if the input stream contents cannot be retrieved
*
* The decoding flags are described in IClassFileReader.
*
* @param stream the given input stream to read
* @param decodingFlag the flag used to decode the class file reader.
* @return a default classfile reader
*
* @see IClassFileReader
* @since 3.2
*/
public static IClassFileReader createDefaultClassFileReader(InputStream stream, int decodingFlag) {
try {
return new ClassFileReader(Util.getInputStreamAsByteArray(stream, -1), decodingFlag);
} catch(ClassFormatException | IOException e) {
return null;
}
}
Create a default classfile reader, able to expose the internal representation of a given classfile
according to the decoding flag used to initialize the reader.
Answer null if the file named fileName doesn't represent a valid .class file.
The fileName has to be an absolute OS path to the given .class file.
The decoding flags are described in IClassFileReader.
Params: - fileName – the name of the file to be read
- decodingFlag – the flag used to decode the class file reader.
See Also: Returns: a default classfile reader
/**
* Create a default classfile reader, able to expose the internal representation of a given classfile
* according to the decoding flag used to initialize the reader.
* Answer null if the file named fileName doesn't represent a valid .class file.
* The fileName has to be an absolute OS path to the given .class file.
*
* The decoding flags are described in IClassFileReader.
*
* @param fileName the name of the file to be read
* @param decodingFlag the flag used to decode the class file reader.
* @return a default classfile reader
*
* @see IClassFileReader
*/
public static IClassFileReader createDefaultClassFileReader(String fileName, int decodingFlag){
try {
return new ClassFileReader(Util.getFileByteContent(new File(fileName)), decodingFlag);
} catch(ClassFormatException | IOException e) {
return null;
}
}
Create a default classfile reader, able to expose the internal representation of a given classfile
according to the decoding flag used to initialize the reader.
Answer null if the file named zipFileName doesn't represent a valid zip file or if the zipEntryName
is not a valid entry name for the specified zip file or if the bytes don't represent a valid
.class file according to the JVM specifications.
The decoding flags are described in IClassFileReader.
Params: - zipFileName – the name of the zip file
- zipEntryName – the name of the entry in the zip file to be read
- decodingFlag – the flag used to decode the class file reader.
See Also: Returns: a default classfile reader
/**
* Create a default classfile reader, able to expose the internal representation of a given classfile
* according to the decoding flag used to initialize the reader.
* Answer null if the file named zipFileName doesn't represent a valid zip file or if the zipEntryName
* is not a valid entry name for the specified zip file or if the bytes don't represent a valid
* .class file according to the JVM specifications.
*
* The decoding flags are described in IClassFileReader.
*
* @param zipFileName the name of the zip file
* @param zipEntryName the name of the entry in the zip file to be read
* @param decodingFlag the flag used to decode the class file reader.
* @return a default classfile reader
* @see IClassFileReader
*/
public static IClassFileReader createDefaultClassFileReader(String zipFileName, String zipEntryName, int decodingFlag){
ZipFile zipFile = null;
try {
if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
System.out.println("(" + Thread.currentThread() + ") [ToolFactory.createDefaultClassFileReader()] Creating ZipFile on " + zipFileName); //$NON-NLS-1$ //$NON-NLS-2$
}
zipFile = new ZipFile(zipFileName);
ZipEntry zipEntry = zipFile.getEntry(zipEntryName);
if (zipEntry == null) {
return null;
}
if (!zipEntryName.toLowerCase().endsWith(SuffixConstants.SUFFIX_STRING_class)) {
return null;
}
byte classFileBytes[] = Util.getZipEntryByteContent(zipEntry, zipFile);
return new ClassFileReader(classFileBytes, decodingFlag);
} catch(ClassFormatException | IOException e) {
return null;
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch(IOException e) {
// ignore
}
}
}
}
Create an instance of the default code formatter.
Params: - options – - the options map to use for formatting with the default code formatter. Recognized options
are documented on
JavaCore#getDefaultOptions()
. If set to null
, then use
the current settings from JavaCore#getOptions
.
See Also: Returns: an instance of the built-in code formatter Deprecated: Use createCodeFormatter(Map)
instead but note the different options
/**
* Create an instance of the default code formatter.
*
* @param options - the options map to use for formatting with the default code formatter. Recognized options
* are documented on <code>JavaCore#getDefaultOptions()</code>. If set to <code>null</code>, then use
* the current settings from <code>JavaCore#getOptions</code>.
* @return an instance of the built-in code formatter
* @see ICodeFormatter
* @see ToolFactory#createCodeFormatter()
* @see JavaCore#getOptions()
* @deprecated Use {@link #createCodeFormatter(Map)} instead but note the different options
*/
public static ICodeFormatter createDefaultCodeFormatter(Map options){
if (options == null) options = JavaCore.getOptions();
return new org.eclipse.jdt.internal.formatter.old.CodeFormatter(options);
}
Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
used to tokenize some source in a Java aware way.
Here is a typical scanning loop:
IScanner scanner = ToolFactory.createScanner(false, false, false, false);
scanner.setSource("int i = 0;".toCharArray());
while (true) {
int token = scanner.getNextToken();
if (token == ITerminalSymbols.TokenNameEOF) break;
System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
}
By default the compliance used to create the scanner is the workspace's compliance when running inside the IDE
or 1.4 if running from outside of a headless eclipse.
Params: - tokenizeComments – if set to
false
, comments will be silently consumed - tokenizeWhiteSpace – if set to
false
, white spaces will be silently consumed, - assertMode – if set to
false
, occurrences of 'assert' will be reported as identifiers (ITerminalSymbols.TokenNameIdentifier
), whereas if set to true
, it would report assert keywords (ITerminalSymbols.TokenNameassert
). Java 1.4 has introduced a new 'assert' keyword. - recordLineSeparator – if set to
true
, the scanner will record positions of encountered line separator ends. In case of multi-character line separators, the last character position is considered. These positions can then be extracted using IScanner.getLineEnds()
. Only non-unicode escape sequences are considered as valid line separators.
See Also: Returns: a scanner
/**
* Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
* used to tokenize some source in a Java aware way.
* Here is a typical scanning loop:
*
* <pre>
* <code>
* IScanner scanner = ToolFactory.createScanner(false, false, false, false);
* scanner.setSource("int i = 0;".toCharArray());
* while (true) {
* int token = scanner.getNextToken();
* if (token == ITerminalSymbols.TokenNameEOF) break;
* System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
* }
* </code>
* </pre>
*
* <p>By default the compliance used to create the scanner is the workspace's compliance when running inside the IDE
* or 1.4 if running from outside of a headless eclipse.
* </p>
*
* @param tokenizeComments if set to <code>false</code>, comments will be silently consumed
* @param tokenizeWhiteSpace if set to <code>false</code>, white spaces will be silently consumed,
* @param assertMode if set to <code>false</code>, occurrences of 'assert' will be reported as identifiers
* ({@link ITerminalSymbols#TokenNameIdentifier}), whereas if set to <code>true</code>, it
* would report assert keywords ({@link ITerminalSymbols#TokenNameassert}). Java 1.4 has introduced
* a new 'assert' keyword.
* @param recordLineSeparator if set to <code>true</code>, the scanner will record positions of encountered line
* separator ends. In case of multi-character line separators, the last character position is considered. These positions
* can then be extracted using {@link IScanner#getLineEnds()}. Only non-unicode escape sequences are
* considered as valid line separators.
* @return a scanner
* @see org.eclipse.jdt.core.compiler.IScanner
* @see #createScanner(boolean, boolean, boolean, String, String)
*/
@SuppressWarnings("javadoc") // references deprecated TokenNameIdentifier
public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean assertMode, boolean recordLineSeparator){
// use default workspace compliance
long complianceLevelValue = CompilerOptions.versionToJdkLevel(JavaCore.getOption(JavaCore.COMPILER_COMPLIANCE));
if (complianceLevelValue == 0) complianceLevelValue = ClassFileConstants.JDK1_4; // fault-tolerance
PublicScanner scanner =
new PublicScanner(
tokenizeComments,
tokenizeWhiteSpace,
false/*nls*/,
assertMode ? ClassFileConstants.JDK1_4 : ClassFileConstants.JDK1_3/*sourceLevel*/,
complianceLevelValue,
null/*taskTags*/,
null/*taskPriorities*/,
true/*taskCaseSensitive*/);
scanner.recordLineSeparator = recordLineSeparator;
return scanner;
}
Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
used to tokenize some source in a Java aware way.
Here is a typical scanning loop:
IScanner scanner = ToolFactory.createScanner(false, false, false, false);
scanner.setSource("int i = 0;".toCharArray());
while (true) {
int token = scanner.getNextToken();
if (token == ITerminalSymbols.TokenNameEOF) break;
System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
}
By default the compliance used to create the scanner is the workspace's compliance when running inside the IDE
or 1.4 if running from outside of a headless eclipse.
Params: - tokenizeComments – if set to
false
, comments will be silently consumed - tokenizeWhiteSpace – if set to
false
, white spaces will be silently consumed, - recordLineSeparator – if set to
true
, the scanner will record positions of encountered line separator ends. In case of multi-character line separators, the last character position is considered. These positions can then be extracted using IScanner.getLineEnds()
. Only non-unicode escape sequences are considered as valid line separators. - sourceLevel – if set to
"1.3"
or null
, occurrences of 'assert' will be reported as identifiers (ITerminalSymbols.TokenNameIdentifier
), whereas if set to "1.4"
, it would report assert keywords (ITerminalSymbols.TokenNameassert
). Java 1.4 has introduced a new 'assert' keyword.
See Also: Returns: a scanner Since: 3.0
/**
* Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
* used to tokenize some source in a Java aware way.
* Here is a typical scanning loop:
*
* <pre>
* <code>
* IScanner scanner = ToolFactory.createScanner(false, false, false, false);
* scanner.setSource("int i = 0;".toCharArray());
* while (true) {
* int token = scanner.getNextToken();
* if (token == ITerminalSymbols.TokenNameEOF) break;
* System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
* }
* </code>
* </pre>
*
* <p>By default the compliance used to create the scanner is the workspace's compliance when running inside the IDE
* or 1.4 if running from outside of a headless eclipse.
* </p>
*
* @param tokenizeComments if set to <code>false</code>, comments will be silently consumed
* @param tokenizeWhiteSpace if set to <code>false</code>, white spaces will be silently consumed,
* @param recordLineSeparator if set to <code>true</code>, the scanner will record positions of encountered line
* separator ends. In case of multi-character line separators, the last character position is considered. These positions
* can then be extracted using {@link IScanner#getLineEnds()}. Only non-unicode escape sequences are
* considered as valid line separators.
* @param sourceLevel if set to <code>"1.3"</code> or <code>null</code>, occurrences of 'assert' will be reported as identifiers
* ({@link ITerminalSymbols#TokenNameIdentifier}), whereas if set to <code>"1.4"</code>, it
* would report assert keywords ({@link ITerminalSymbols#TokenNameassert}). Java 1.4 has introduced
* a new 'assert' keyword.
* @return a scanner
* @see org.eclipse.jdt.core.compiler.IScanner
* @see #createScanner(boolean, boolean, boolean, String, String)
* @since 3.0
*/
@SuppressWarnings("javadoc") // references deprecated TokenNameIdentifier
public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean recordLineSeparator, String sourceLevel) {
// use default workspace compliance
long complianceLevelValue = CompilerOptions.versionToJdkLevel(JavaCore.getOption(JavaCore.COMPILER_COMPLIANCE));
if (complianceLevelValue == 0) complianceLevelValue = ClassFileConstants.JDK1_4; // fault-tolerance
long sourceLevelValue = CompilerOptions.versionToJdkLevel(sourceLevel);
if (sourceLevelValue == 0) sourceLevelValue = ClassFileConstants.JDK1_3; // fault-tolerance
PublicScanner scanner =
new PublicScanner(
tokenizeComments,
tokenizeWhiteSpace,
false/*nls*/,
sourceLevelValue /*sourceLevel*/,
complianceLevelValue,
null/*taskTags*/,
null/*taskPriorities*/,
true/*taskCaseSensitive*/);
scanner.recordLineSeparator = recordLineSeparator;
return scanner;
}
Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
used to tokenize some source in a Java aware way.
Here is a typical scanning loop:
IScanner scanner = ToolFactory.createScanner(false, false, false, false);
scanner.setSource("int i = 0;".toCharArray());
while (true) {
int token = scanner.getNextToken();
if (token == ITerminalSymbols.TokenNameEOF) break;
System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
}
Params: - tokenizeComments – if set to
false
, comments will be silently consumed - tokenizeWhiteSpace – if set to
false
, white spaces will be silently consumed, - recordLineSeparator – if set to
true
, the scanner will record positions of encountered line separator ends. In case of multi-character line separators, the last character position is considered. These positions can then be extracted using IScanner.getLineEnds()
. Only non-unicode escape sequences are considered as valid line separators. - sourceLevel – if set to
"1.3"
or null
, occurrences of 'assert' will be reported as identifiers (ITerminalSymbols.TokenNameIdentifier
), whereas if set to "1.4"
, it would report assert keywords (ITerminalSymbols.TokenNameassert
). Java 1.4 has introduced a new 'assert' keyword. - complianceLevel – This is used to support the Unicode 4.0 character sets. if set to 1.5 or above,
the Unicode 4.0 is supported, otherwise Unicode 3.0 is supported.
See Also: Returns: a scanner Since: 3.1
/**
* Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
* used to tokenize some source in a Java aware way.
* Here is a typical scanning loop:
*
* <pre>
* <code>
* IScanner scanner = ToolFactory.createScanner(false, false, false, false);
* scanner.setSource("int i = 0;".toCharArray());
* while (true) {
* int token = scanner.getNextToken();
* if (token == ITerminalSymbols.TokenNameEOF) break;
* System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
* }
* </code>
* </pre>
*
* @param tokenizeComments if set to <code>false</code>, comments will be silently consumed
* @param tokenizeWhiteSpace if set to <code>false</code>, white spaces will be silently consumed,
* @param recordLineSeparator if set to <code>true</code>, the scanner will record positions of encountered line
* separator ends. In case of multi-character line separators, the last character position is considered. These positions
* can then be extracted using {@link IScanner#getLineEnds()}. Only non-unicode escape sequences are
* considered as valid line separators.
* @param sourceLevel if set to <code>"1.3"</code> or <code>null</code>, occurrences of 'assert' will be reported as identifiers
* ({@link ITerminalSymbols#TokenNameIdentifier}), whereas if set to <code>"1.4"</code>, it
* would report assert keywords ({@link ITerminalSymbols#TokenNameassert}). Java 1.4 has introduced
* a new 'assert' keyword.
* @param complianceLevel This is used to support the Unicode 4.0 character sets. if set to 1.5 or above,
* the Unicode 4.0 is supported, otherwise Unicode 3.0 is supported.
* @return a scanner
* @see org.eclipse.jdt.core.compiler.IScanner
*
* @since 3.1
*/
@SuppressWarnings("javadoc") // references deprecated TokenNameIdentifier
public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean recordLineSeparator, String sourceLevel, String complianceLevel) {
return createScanner(tokenizeComments, tokenizeWhiteSpace, recordLineSeparator, sourceLevel, complianceLevel, true);
}
Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
used to tokenize some source in a Java aware way.
Here is a typical scanning loop:
IScanner scanner = ToolFactory.createScanner(false, false, false, false);
scanner.setSource("int i = 0;".toCharArray());
while (true) {
int token = scanner.getNextToken();
if (token == ITerminalSymbols.TokenNameEOF) break;
System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
}
Params: - tokenizeComments – if set to
false
, comments will be silently consumed - tokenizeWhiteSpace – if set to
false
, white spaces will be silently consumed, - recordLineSeparator – if set to
true
, the scanner will record positions of encountered line separator ends. In case of multi-character line separators, the last character position is considered. These positions can then be extracted using IScanner.getLineEnds()
. Only non-unicode escape sequences are considered as valid line separators. - sourceLevel – if set to
"1.3"
or null
, occurrences of 'assert' will be reported as identifiers (ITerminalSymbols.TokenNameIdentifier
), whereas if set to "1.4"
, it would report assert keywords (ITerminalSymbols.TokenNameassert
). Java 1.4 has introduced a new 'assert' keyword. - complianceLevel – This is used to support the Unicode 4.0 character sets. if set to 1.5 or above,
the Unicode 4.0 is supported, otherwise Unicode 3.0 is supported.
- enablePreview – specify whether the scanner should look for preview language features for the specified compliance level
See Also: Returns: a scanner Since: 3.20
/**
* Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
* used to tokenize some source in a Java aware way.
* Here is a typical scanning loop:
*
* <pre>
* <code>
* IScanner scanner = ToolFactory.createScanner(false, false, false, false);
* scanner.setSource("int i = 0;".toCharArray());
* while (true) {
* int token = scanner.getNextToken();
* if (token == ITerminalSymbols.TokenNameEOF) break;
* System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
* }
* </code>
* </pre>
*
* @param tokenizeComments if set to <code>false</code>, comments will be silently consumed
* @param tokenizeWhiteSpace if set to <code>false</code>, white spaces will be silently consumed,
* @param recordLineSeparator if set to <code>true</code>, the scanner will record positions of encountered line
* separator ends. In case of multi-character line separators, the last character position is considered. These positions
* can then be extracted using {@link IScanner#getLineEnds()}. Only non-unicode escape sequences are
* considered as valid line separators.
* @param sourceLevel if set to <code>"1.3"</code> or <code>null</code>, occurrences of 'assert' will be reported as identifiers
* ({@link ITerminalSymbols#TokenNameIdentifier}), whereas if set to <code>"1.4"</code>, it
* would report assert keywords ({@link ITerminalSymbols#TokenNameassert}). Java 1.4 has introduced
* a new 'assert' keyword.
* @param complianceLevel This is used to support the Unicode 4.0 character sets. if set to 1.5 or above,
* the Unicode 4.0 is supported, otherwise Unicode 3.0 is supported.
* @param enablePreview specify whether the scanner should look for preview language features for the specified compliance level
* @return a scanner
* @see org.eclipse.jdt.core.compiler.IScanner
*
* @since 3.20
*/
@SuppressWarnings("javadoc") // references deprecated TokenNameIdentifier
public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean recordLineSeparator, String sourceLevel, String complianceLevel, boolean enablePreview) {
PublicScanner scanner = null;
long sourceLevelValue = CompilerOptions.versionToJdkLevel(sourceLevel);
if (sourceLevelValue == 0) sourceLevelValue = ClassFileConstants.JDK1_3; // fault-tolerance
long complianceLevelValue = CompilerOptions.versionToJdkLevel(complianceLevel);
if (complianceLevelValue == 0) complianceLevelValue = ClassFileConstants.JDK1_4; // fault-tolerance
scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/,sourceLevelValue /*sourceLevel*/, complianceLevelValue, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/, enablePreview);
scanner.recordLineSeparator = recordLineSeparator;
return scanner;
}
}