diff options
author | Tom Schindl | 2015-02-13 13:41:25 +0000 |
---|---|---|
committer | Tom Schindl | 2015-02-13 13:41:25 +0000 |
commit | 754de0a3969032f0716aebecf9540233f01eb48c (patch) | |
tree | 0d7dfd739811d57894467d4f7b535d2e9b5d308b /demos | |
parent | 2f5e05990b7bff7e800e80a4735c45584064d6d4 (diff) | |
download | org.eclipse.efxclipse-754de0a3969032f0716aebecf9540233f01eb48c.tar.gz org.eclipse.efxclipse-754de0a3969032f0716aebecf9540233f01eb48c.tar.xz org.eclipse.efxclipse-754de0a3969032f0716aebecf9540233f01eb48c.zip |
Bug 459868 - Add sample for syntax highlighting
Diffstat (limited to 'demos')
21 files changed, 2136 insertions, 0 deletions
diff --git a/demos/CodeEditor/.classpath b/demos/CodeEditor/.classpath new file mode 100644 index 000000000..c895e2809 --- /dev/null +++ b/demos/CodeEditor/.classpath @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> + <classpathentry kind="con" path="org.eclipse.fx.ide.jdt.core.JAVAFX_CONTAINER"/> + <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.fx.text"/> + <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.fx.text.ui"/> + <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.fx.ui.controls"/> + <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.fx.core"/> + <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.fx.ui.services"/> + <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.text"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/demos/CodeEditor/.gitignore b/demos/CodeEditor/.gitignore new file mode 100644 index 000000000..4a95481e6 --- /dev/null +++ b/demos/CodeEditor/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/build/ diff --git a/demos/CodeEditor/.project b/demos/CodeEditor/.project new file mode 100644 index 000000000..0d82fc343 --- /dev/null +++ b/demos/CodeEditor/.project @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>CodeEditor</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.xtext.ui.shared.xtextBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.xtext.ui.shared.xtextNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/demos/CodeEditor/.settings/org.eclipse.jdt.core.prefs b/demos/CodeEditor/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..a698e5967 --- /dev/null +++ b/demos/CodeEditor/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/demos/CodeEditor/build.fxbuild b/demos/CodeEditor/build.fxbuild new file mode 100644 index 000000000..7b51ae658 --- /dev/null +++ b/demos/CodeEditor/build.fxbuild @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="ASCII"?> +<anttasks:AntTask xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:anttasks="http://org.eclipse.fx.ide.jdt/1.0" buildDirectory="${project}/build"> + <deploy packagingFormat="all"> + <application name="CodeEditor" mainclass="application.Main" version="1.0.0" toolkit="fx"/> + <info title="Java File Editor" vendor="BestSolution.at"/> + </deploy> + <signjar/> +</anttasks:AntTask> diff --git a/demos/CodeEditor/src/application/Main.java b/demos/CodeEditor/src/application/Main.java new file mode 100644 index 000000000..8b9f7ca21 --- /dev/null +++ b/demos/CodeEditor/src/application/Main.java @@ -0,0 +1,159 @@ +package application; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; + +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.control.Menu; +import javafx.scene.control.MenuBar; +import javafx.scene.control.MenuItem; +import javafx.scene.control.RadioMenuItem; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.scene.control.ToggleGroup; +import javafx.scene.layout.BorderPane; +import javafx.stage.FileChooser; +import javafx.stage.FileChooser.ExtensionFilter; +import javafx.stage.Stage; + +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.rules.FastPartitioner; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; + +import application.text.FastJavaPartitionScanner; +import application.text.IJavaPartitions; +import application.text.JavaSourceConfiguration; + +public class Main extends Application { + @Override + public void start(Stage primaryStage) { + BorderPane root = new BorderPane(); + MenuBar b = new MenuBar(); + Menu m = new Menu("File"); + MenuItem item = new MenuItem("Open ..."); + m.getItems().add(item); + b.getMenus().add(m); + + { + Menu themes = new Menu("Themes"); + + ToggleGroup g = new ToggleGroup(); + + RadioMenuItem defaultTheme = new RadioMenuItem("Default"); + defaultTheme.setSelected(true); + defaultTheme.setOnAction(e -> { + Scene scene = primaryStage.getScene(); + scene.getStylesheets().clear(); + scene.getStylesheets().add(getClass().getResource("default.css").toExternalForm()); + scene.getStylesheets().add(Main.class.getResource("highlight.css").toExternalForm()); + + }); + + RadioMenuItem dark = new RadioMenuItem("Dark"); + dark.setOnAction(e -> { + Scene scene = primaryStage.getScene(); + scene.getStylesheets().clear(); + scene.getStylesheets().add(getClass().getResource("dark-default.css").toExternalForm()); + scene.getStylesheets().add(Main.class.getResource("dark-highlight.css").toExternalForm()); + + }); + themes.getItems().addAll(defaultTheme,dark); + + m.getItems().add(themes); + g.getToggles().addAll(defaultTheme,dark); + } + + root.setTop(b); + + TabPane tabPane = new TabPane(); + root.setCenter(tabPane); + + m.setOnAction(e -> { + FileChooser c = new FileChooser(); + c.getExtensionFilters().add(new ExtensionFilter("Java Source Files", Collections.singletonList("*.java"))); + c.setSelectedExtensionFilter(c.getExtensionFilters().get(0)); + List<File> showOpenMultipleDialog = c.showOpenMultipleDialog(primaryStage); + if( showOpenMultipleDialog != null ) { + for( File f : showOpenMultipleDialog ) { + Path path = Paths.get(f.toURI()); + Tab t = new Tab(path.getFileName().toString()); + t.setContent(createViewer(path).getTextWidget()); + tabPane.getTabs().add(t); + } + } + }); + + Scene scene = new Scene(root, 400, 400); + scene.getStylesheets().add(getClass().getResource("default.css").toExternalForm()); + scene.getStylesheets().add(Main.class.getResource("highlight.css").toExternalForm()); + + primaryStage.setScene(scene); + primaryStage.show(); + } + + public SourceViewer createViewer(Path p) { + SourceViewer viewer = new SourceViewer(); + SourceViewerConfiguration configuration = createConfig(); + Document document = createDocument(p); + IDocumentPartitioner partitioner = createPartitioner(); + + if (document instanceof IDocumentExtension3) { + ((IDocumentExtension3) document).setDocumentPartitioner( + configuration.getConfiguredDocumentPartitioning(viewer), partitioner); + } else { + document.setDocumentPartitioner(partitioner); + } + document.setDocumentPartitioner(partitioner); + partitioner.connect(document); + + viewer.configure(configuration); + viewer.setDocument(document); + return viewer; + + } + + private SourceViewerConfiguration createConfig() { + return new JavaSourceConfiguration(); + } + + private IDocumentPartitioner createPartitioner() { + return new FastPartitioner(new FastJavaPartitionScanner(), new String[] { IJavaPartitions.JAVA_DOC, + IJavaPartitions.JAVA_MULTI_LINE_COMMENT, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT, + IJavaPartitions.JAVA_STRING, IJavaPartitions.JAVA_CHARACTER }); + } + + private Document createDocument(Path p) { + return new Document(getFile(p)); + } + + private String getFile(Path p) { + try (BufferedReader reader = Files.newBufferedReader(p)) { + StringBuilder b = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + // FIXME We need to replace TABs for now + b.append(line.replaceAll("\t", " ") + "\n"); + } + reader.close(); + return b.toString(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return ""; + } + + public static void main(String[] args) { + launch(args); + } +} diff --git a/demos/CodeEditor/src/application/dark-default.css b/demos/CodeEditor/src/application/dark-default.css new file mode 100644 index 000000000..196bef392 --- /dev/null +++ b/demos/CodeEditor/src/application/dark-default.css @@ -0,0 +1,22 @@ +.root { + -fx-base: #4d5052; + -fx-background: #4d5052; + -fx-control-inner-background: #4d5052; + -fx-text-base-color: #c7c7c7; + /* @SuppressWarning */ + -compensator-default-text: -fx-text-background-color; + /* @SuppressWarning */ + -compensator-extra1: /*#957d47*/ derive(-fx-text-background-color, -30%); +} + +.cell-text-extra { + -fx-fill: -compensator-extra1; +} + +.cell-text-default { + -fx-fill: -compensator-default-text; +} + +.menu-bar { + -fx-background-color: transparent; +}
\ No newline at end of file diff --git a/demos/CodeEditor/src/application/dark-highlight.css b/demos/CodeEditor/src/application/dark-highlight.css new file mode 100644 index 000000000..5275249a8 --- /dev/null +++ b/demos/CodeEditor/src/application/dark-highlight.css @@ -0,0 +1,59 @@ +.java.styled-text-area .selection-marker { + -fx-background-color: #2b5696; +} + +.java.styled-text-area .java_string { + -styled-text-color: #7c986c; +} + +.java.styled-text-area .java_default { + -styled-text-color: #b8c4d1; +} + +.java.styled-text-area .java_annotation { + -styled-text-color: rgb(200, 200, 200); +} + +.java.styled-text-area .java_keyword { + -styled-text-color: #d78b40; + -fx-font-weight: bold; +} + +.java.styled-text-area .java_operator { + -styled-text-color: #b8c4d1; +} + +.java.styled-text-area .java_bracket { + -styled-text-color: #b8c4d1; +} + +.java.styled-text-area .java_keyword_return { + -styled-text-color: #d78b40; + -fx-font-weight: bold; +} + +.java.styled-text-area .java_comment_task_tag { + -styled-text-color: rgb(127, 159, 191); +} + +.java.styled-text-area .java_doc_link { + -styled-text-color: #74a567; + -fx-font-weight: bold; +} + +.java.styled-text-area .java_doc_default { + -styled-text-color: #74a567; +} + +.java.styled-text-area .java_multi_line_comment { + -styled-text-color: #929292; +} + +.java.styled-text-area .java_single_line_comment { + -styled-text-color: #929292; +} + +.java.styled-text-area .java_doc_tag { + -fx-fill: #74a567; + -fx-font-weight: bold; +}
\ No newline at end of file diff --git a/demos/CodeEditor/src/application/default.css b/demos/CodeEditor/src/application/default.css new file mode 100644 index 000000000..198cd70e2 --- /dev/null +++ b/demos/CodeEditor/src/application/default.css @@ -0,0 +1,18 @@ +.root { + /* @SuppressWarning */ + -compensator-default-text: -fx-text-background-color; + /* @SuppressWarning */ + -compensator-extra1: /*#957d47*/ derive(-fx-text-background-color, 110%); +} + +.cell-text-extra { + -fx-fill: -compensator-extra1; +} + +.cell-text-default { + -fx-fill: -compensator-default-text; +} + +.menu-bar { + -fx-background-color: transparent; +}
\ No newline at end of file diff --git a/demos/CodeEditor/src/application/highlight.css b/demos/CodeEditor/src/application/highlight.css new file mode 100644 index 000000000..ff6e06d23 --- /dev/null +++ b/demos/CodeEditor/src/application/highlight.css @@ -0,0 +1,53 @@ +.java.styled-text-area .java_string { + -styled-text-color: rgb(42, 0, 255); +} + +.java.styled-text-area .java_default { + -styled-text-color: rgb(0,0,0); +} + +.java.styled-text-area .java_annotation { + -styled-text-color: rgb(200, 200, 200); +} + +.java.styled-text-area .java_keyword { + -styled-text-color: rgb(127, 0, 85); + -fx-font-weight: bold; +} + +.java.styled-text-area .java_operator { + -styled-text-color: rgb(0,0,0); +} + +.java.styled-text-area .java_bracket { + -styled-text-color: rgb(0,0,0); +} + +.java.styled-text-area .java_keyword_return { + -styled-text-color: rgb(127, 0, 85); + -fx-font-weight: bold; +} + +.java.styled-text-area .java_comment_task_tag { + -styled-text-color: rgb(127, 159, 191); +} + +.java.styled-text-area .java_doc_link { + -styled-text-color: rgb(63, 63, 191); +} + +.java.styled-text-area .java_doc_default { + -styled-text-color: rgb(63, 95, 191); +} + +.java.styled-text-area .java_multi_line_comment { + -styled-text-color: rgb(63, 127, 95); +} + +.java.styled-text-area .java_single_line_comment { + -styled-text-color: rgb(63, 127, 95); +} + +.java.styled-text-area .java_doc_tag { + -styled-text-color: rgb(127, 127, 159); +}
\ No newline at end of file diff --git a/demos/CodeEditor/src/application/text/AbstractJavaScanner.java b/demos/CodeEditor/src/application/text/AbstractJavaScanner.java new file mode 100644 index 000000000..bd4e2982d --- /dev/null +++ b/demos/CodeEditor/src/application/text/AbstractJavaScanner.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package application.text; + +import java.util.List; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.BufferedRuleBasedScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.Token; + +public abstract class AbstractJavaScanner extends BufferedRuleBasedScanner { + + public AbstractJavaScanner() { + } + + public final void initialize() { + initializeRules(); + } + + abstract protected List<IRule> createRules(); + + private void initializeRules() { + List<IRule> rules= createRules(); + if (rules != null) { + IRule[] result= new IRule[rules.size()]; + rules.toArray(result); + setRules(result); + } + } + + protected Token getToken(String key) { + switch (key) { + case IJavaColorConstants.JAVA_STRING: + return new Token(new TextAttribute(IJavaColorConstants.JAVA_STRING)); + case IJavaColorConstants.JAVA_DEFAULT: + return new Token(new TextAttribute(IJavaColorConstants.JAVA_DEFAULT)); + case IJavaColorConstants.ANNOTATION: + return new Token(new TextAttribute(IJavaColorConstants.ANNOTATION)); + case IJavaColorConstants.JAVA_KEYWORD: + return new Token(new TextAttribute(IJavaColorConstants.JAVA_KEYWORD)); + case IJavaColorConstants.JAVA_OPERATOR: + return new Token(new TextAttribute(IJavaColorConstants.JAVA_OPERATOR)); + case IJavaColorConstants.JAVA_BRACKET: + return new Token(new TextAttribute(IJavaColorConstants.JAVA_BRACKET)); + case IJavaColorConstants.JAVA_KEYWORD_RETURN: + return new Token(new TextAttribute(IJavaColorConstants.JAVA_KEYWORD_RETURN)); + case IJavaColorConstants.TASK_TAG: + return new Token(new TextAttribute(IJavaColorConstants.TASK_TAG)); + case IJavaColorConstants.JAVADOC_LINK: + return new Token(new TextAttribute(IJavaColorConstants.JAVADOC_LINK)); + case IJavaColorConstants.JAVADOC_DEFAULT: + return new Token(new TextAttribute(IJavaColorConstants.JAVADOC_DEFAULT)); + case IJavaColorConstants.JAVA_MULTI_LINE_COMMENT: + return new Token(new TextAttribute(IJavaColorConstants.JAVA_MULTI_LINE_COMMENT)); + case IJavaColorConstants.JAVA_SINGLE_LINE_COMMENT: + return new Token(new TextAttribute(IJavaColorConstants.JAVA_SINGLE_LINE_COMMENT)); + case IJavaColorConstants.JAVADOC_TAG: + return new Token(new TextAttribute(IJavaColorConstants.JAVADOC_TAG)); + default: + throw new IllegalStateException("Unknown key '"+ key+"'"); + } + } +} diff --git a/demos/CodeEditor/src/application/text/FastJavaPartitionScanner.java b/demos/CodeEditor/src/application/text/FastJavaPartitionScanner.java new file mode 100644 index 000000000..5a0bac5f7 --- /dev/null +++ b/demos/CodeEditor/src/application/text/FastJavaPartitionScanner.java @@ -0,0 +1,534 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package application.text; + + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.rules.BufferedDocumentScanner; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IPartitionTokenScanner; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.Token; + + +/** + * This scanner recognizes the JavaDoc comments, Java multi line comments, Java single line comments, + * Java strings and Java characters. + */ +public class FastJavaPartitionScanner implements IPartitionTokenScanner, IJavaPartitions { + + // states + private static final int JAVA= 0; + private static final int SINGLE_LINE_COMMENT= 1; + private static final int MULTI_LINE_COMMENT= 2; + private static final int JAVADOC= 3; + private static final int CHARACTER= 4; + private static final int STRING= 5; + + // beginning of prefixes and postfixes + private static final int NONE= 0; + private static final int BACKSLASH= 1; // postfix for STRING and CHARACTER + private static final int SLASH= 2; // prefix for SINGLE_LINE or MULTI_LINE or JAVADOC + private static final int SLASH_STAR= 3; // prefix for MULTI_LINE_COMMENT or JAVADOC + private static final int SLASH_STAR_STAR= 4; // prefix for MULTI_LINE_COMMENT or JAVADOC + private static final int STAR= 5; // postfix for MULTI_LINE_COMMENT or JAVADOC + private static final int CARRIAGE_RETURN=6; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT + + /** The scanner. */ + private final BufferedDocumentScanner fScanner= new BufferedDocumentScanner(1000); // faster implementation + + /** The offset of the last returned token. */ + private int fTokenOffset; + /** The length of the last returned token. */ + private int fTokenLength; + + /** The state of the scanner. */ + private int fState; + /** The last significant characters read. */ + private int fLast; + /** The amount of characters already read on first call to nextToken(). */ + private int fPrefixLength; + + // emulate JavaPartitionScanner + private boolean fEmulate= false; + private int fJavaOffset; + private int fJavaLength; + + private final IToken[] fTokens= new IToken[] { + new Token(null), + new Token(JAVA_SINGLE_LINE_COMMENT), + new Token(JAVA_MULTI_LINE_COMMENT), + new Token(JAVA_DOC), + new Token(JAVA_CHARACTER), + new Token(JAVA_STRING) + }; + + public FastJavaPartitionScanner(boolean emulate) { + fEmulate= emulate; + } + + public FastJavaPartitionScanner() { + this(false); + } + + /* + * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken() + */ + public IToken nextToken() { + + // emulate JavaPartitionScanner + if (fEmulate) { + if (fJavaOffset != -1 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) { + fTokenOffset += fTokenLength; + return fTokens[JAVA]; + } else { + fJavaOffset= -1; + fJavaLength= 0; + } + } + + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + + while (true) { + final int ch= fScanner.read(); + + // characters + switch (ch) { + case ICharacterScanner.EOF: + if (fTokenLength > 0) { + fLast= NONE; // ignore last + return preFix(fState, JAVA, NONE, 0); + + } else { + fLast= NONE; + fPrefixLength= 0; + return Token.EOF; + } + + case '\r': + // emulate JavaPartitionScanner + if (!fEmulate && fLast != CARRIAGE_RETURN) { + fLast= CARRIAGE_RETURN; + fTokenLength++; + continue; + + } else { + + switch (fState) { + case SINGLE_LINE_COMMENT: + case CHARACTER: + case STRING: + if (fTokenLength > 0) { + IToken token= fTokens[fState]; + + // emulate JavaPartitionScanner + if (fEmulate) { + fTokenLength++; + fLast= NONE; + fPrefixLength= 0; + } else { + fLast= CARRIAGE_RETURN; + fPrefixLength= 1; + } + + fState= JAVA; + return token; + + } else { + consume(); + continue; + } + + default: + consume(); + continue; + } + } + + case '\n': + switch (fState) { + case SINGLE_LINE_COMMENT: + case CHARACTER: + case STRING: + // assert(fTokenLength > 0); + return postFix(fState); + + default: + consume(); + continue; + } + + default: + if (!fEmulate && fLast == CARRIAGE_RETURN) { + switch (fState) { + case SINGLE_LINE_COMMENT: + case CHARACTER: + case STRING: + + int last; + int newState; + switch (ch) { + case '/': + last= SLASH; + newState= JAVA; + break; + + case '*': + last= STAR; + newState= JAVA; + break; + + case '\'': + last= NONE; + newState= CHARACTER; + break; + + case '"': + last= NONE; + newState= STRING; + break; + + case '\r': + last= CARRIAGE_RETURN; + newState= JAVA; + break; + + case '\\': + last= BACKSLASH; + newState= JAVA; + break; + + default: + last= NONE; + newState= JAVA; + break; + } + + fLast= NONE; // ignore fLast + return preFix(fState, newState, last, 1); + + default: + break; + } + } + } + + // states + switch (fState) { + case JAVA: + switch (ch) { + case '/': + if (fLast == SLASH) { + if (fTokenLength - getLastLength(fLast) > 0) { + return preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2); + } else { + preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + + } else { + fTokenLength++; + fLast= SLASH; + break; + } + + case '*': + if (fLast == SLASH) { + if (fTokenLength - getLastLength(fLast) > 0) + return preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2); + else { + preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + + } else { + consume(); + break; + } + + case '\'': + fLast= NONE; // ignore fLast + if (fTokenLength > 0) + return preFix(JAVA, CHARACTER, NONE, 1); + else { + preFix(JAVA, CHARACTER, NONE, 1); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + + case '"': + fLast= NONE; // ignore fLast + if (fTokenLength > 0) + return preFix(JAVA, STRING, NONE, 1); + else { + preFix(JAVA, STRING, NONE, 1); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + + default: + consume(); + break; + } + break; + + case SINGLE_LINE_COMMENT: + consume(); + break; + + case JAVADOC: + switch (ch) { + case '/': + switch (fLast) { + case SLASH_STAR_STAR: + return postFix(MULTI_LINE_COMMENT); + + case STAR: + return postFix(JAVADOC); + + default: + consume(); + break; + } + break; + + case '*': + fTokenLength++; + fLast= STAR; + break; + + default: + consume(); + break; + } + break; + + case MULTI_LINE_COMMENT: + switch (ch) { + case '*': + if (fLast == SLASH_STAR) { + fLast= SLASH_STAR_STAR; + fTokenLength++; + fState= JAVADOC; + } else { + fTokenLength++; + fLast= STAR; + } + break; + + case '/': + if (fLast == STAR) { + return postFix(MULTI_LINE_COMMENT); + } else { + consume(); + break; + } + + default: + consume(); + break; + } + break; + + case STRING: + switch (ch) { + case '\\': + fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH; + fTokenLength++; + break; + + case '\"': + if (fLast != BACKSLASH) { + return postFix(STRING); + + } else { + consume(); + break; + } + + default: + consume(); + break; + } + break; + + case CHARACTER: + switch (ch) { + case '\\': + fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH; + fTokenLength++; + break; + + case '\'': + if (fLast != BACKSLASH) { + return postFix(CHARACTER); + + } else { + consume(); + break; + } + + default: + consume(); + break; + } + break; + } + } + } + + private static final int getLastLength(int last) { + switch (last) { + default: + return -1; + + case NONE: + return 0; + + case CARRIAGE_RETURN: + case BACKSLASH: + case SLASH: + case STAR: + return 1; + + case SLASH_STAR: + return 2; + + case SLASH_STAR_STAR: + return 3; + } + } + + private final void consume() { + fTokenLength++; + fLast= NONE; + } + + private final IToken postFix(int state) { + fTokenLength++; + fLast= NONE; + fState= JAVA; + fPrefixLength= 0; + return fTokens[state]; + } + + private final IToken preFix(int state, int newState, int last, int prefixLength) { + // emulate JavaPartitionScanner + if (fEmulate && state == JAVA && (fTokenLength - getLastLength(fLast) > 0)) { + fTokenLength -= getLastLength(fLast); + fJavaOffset= fTokenOffset; + fJavaLength= fTokenLength; + fTokenLength= 1; + fState= newState; + fPrefixLength= prefixLength; + fLast= last; + return fTokens[state]; + + } else { + fTokenLength -= getLastLength(fLast); + fLast= last; + fPrefixLength= prefixLength; + IToken token= fTokens[state]; + fState= newState; + return token; + } + } + + private static int getState(String contentType) { + + if (contentType == null) + return JAVA; + + else if (contentType.equals(JAVA_SINGLE_LINE_COMMENT)) + return SINGLE_LINE_COMMENT; + + else if (contentType.equals(JAVA_MULTI_LINE_COMMENT)) + return MULTI_LINE_COMMENT; + + else if (contentType.equals(JAVA_DOC)) + return JAVADOC; + + else if (contentType.equals(JAVA_STRING)) + return STRING; + + else if (contentType.equals(JAVA_CHARACTER)) + return CHARACTER; + + else + return JAVA; + } + + /* + * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int) + */ + public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) { + + fScanner.setRange(document, offset, length); + fTokenOffset= partitionOffset; + fTokenLength= 0; + fPrefixLength= offset - partitionOffset; + fLast= NONE; + + if (offset == partitionOffset) { + // restart at beginning of partition + fState= JAVA; + } else { + fState= getState(contentType); + } + + // emulate JavaPartitionScanner + if (fEmulate) { + fJavaOffset= -1; + fJavaLength= 0; + } + } + + /* + * @see ITokenScanner#setRange(IDocument, int, int) + */ + public void setRange(IDocument document, int offset, int length) { + + fScanner.setRange(document, offset, length); + fTokenOffset= offset; + fTokenLength= 0; + fPrefixLength= 0; + fLast= NONE; + fState= JAVA; + + // emulate JavaPartitionScanner + if (fEmulate) { + fJavaOffset= -1; + fJavaLength= 0; + } + } + + /* + * @see ITokenScanner#getTokenLength() + */ + public int getTokenLength() { + return fTokenLength; + } + + /* + * @see ITokenScanner#getTokenOffset() + */ + public int getTokenOffset() { + return fTokenOffset; + } + +} diff --git a/demos/CodeEditor/src/application/text/IJavaColorConstants.java b/demos/CodeEditor/src/application/text/IJavaColorConstants.java new file mode 100644 index 000000000..0434d9ce9 --- /dev/null +++ b/demos/CodeEditor/src/application/text/IJavaColorConstants.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright (c) 2000, 2013 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package application.text; + +/** + * Color keys used for syntax highlighting Java + * code and Javadoc compliant comments. + * A <code>IColorManager</code> is responsible for mapping + * concrete colors to these keys. + * <p> + * This interface declares static final fields only; it is not intended to be + * implemented. + * </p> + * + * @see org.eclipse.jdt.ui.text.IColorManager + * @see org.eclipse.jdt.ui.text.IColorManagerExtension + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ +public interface IJavaColorConstants { + + /** + * Note: This constant is for internal use only. Clients should not use this constant. The + * prefix all color constants start with (value <code>"java_"</code>). + */ + String PREFIX= "java_"; //$NON-NLS-1$ + + /** The color key for multi-line comments in Java code + * (value <code>"java_multi_line_comment"</code>). + */ + String JAVA_MULTI_LINE_COMMENT= "java_multi_line_comment"; //$NON-NLS-1$ + + /** The color key for single-line comments in Java code + * (value <code>"java_single_line_comment"</code>). + */ + String JAVA_SINGLE_LINE_COMMENT= "java_single_line_comment"; //$NON-NLS-1$ + + /** The color key for Java keywords in Java code + * (value <code>"java_keyword"</code>). + */ + String JAVA_KEYWORD= "java_keyword"; //$NON-NLS-1$ + + /** The color key for string and character literals in Java code + * (value <code>"java_string"</code>). + */ + String JAVA_STRING= "java_string"; //$NON-NLS-1$ + + /** The color key for method names in Java code + * (value <code>"java_method_name"</code>). + * + * @since 3.0 + * @deprecated replaced as of 3.1 by an equivalent semantic highlighting, see {@link org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightings#METHOD} + */ + String JAVA_METHOD_NAME= "java_method_name"; //$NON-NLS-1$ + + /** The color key for keyword 'return' in Java code + * (value <code>"java_keyword_return"</code>). + * + * @since 3.0 + */ + String JAVA_KEYWORD_RETURN= "java_keyword_return"; //$NON-NLS-1$ + + /** The color key for operators in Java code + * (value <code>"java_operator"</code>). + * + * @since 3.0 + */ + String JAVA_OPERATOR= "java_operator"; //$NON-NLS-1$ + + /** The color key for brackets in Java code + * (value <code>"java_bracket"</code>). + * + * @since 3.3 + */ + String JAVA_BRACKET= "java_bracket"; //$NON-NLS-1$ + + /** + * The color key for everything in Java code for which no other color is specified + * (value <code>"java_default"</code>). + */ + String JAVA_DEFAULT= "java_default"; //$NON-NLS-1$ + + /** + * The color key for the Java built-in types such as <code>int</code> and <code>char</code> in Java code + * (value <code>"java_type"</code>). + * + * @deprecated no longer used, replaced by <code>JAVA_KEYWORD</code> + */ + String JAVA_TYPE= "java_type"; //$NON-NLS-1$ + + /** + * The color key for annotations + * (value <code>"java_annotation"</code>). + * + * @since 3.1 + * @deprecated replaced as of 3.2 by an equivalent semantic highlighting, see {@link org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightings#ANNOTATION} + */ + String JAVA_ANNOTATION= "java_annotation"; //$NON-NLS-1$ + + /** + * The color key for task tags in java comments + * (value <code>"java_comment_task_tag"</code>). + * + * @since 2.1 + */ + String TASK_TAG= "java_comment_task_tag"; //$NON-NLS-1$ + + /** + * The color key for JavaDoc keywords (<code>@foo</code>) in JavaDoc comments + * (value <code>"java_doc_keyword"</code>). + */ + String JAVADOC_KEYWORD= "java_doc_keyword"; //$NON-NLS-1$ + + /** + * The color key for HTML tags (<code><foo></code>) in JavaDoc comments + * (value <code>"java_doc_tag"</code>). + */ + String JAVADOC_TAG= "java_doc_tag"; //$NON-NLS-1$ + + /** + * The color key for JavaDoc links (<code>{foo}</code>) in JavaDoc comments + * (value <code>"java_doc_link"</code>). + */ + String JAVADOC_LINK= "java_doc_link"; //$NON-NLS-1$ + + /** + * The color key for everything in JavaDoc comments for which no other color is specified + * (value <code>"java_doc_default"</code>). + */ + String JAVADOC_DEFAULT= "java_doc_default"; //$NON-NLS-1$ + + //---------- Properties File Editor ---------- + + /** + * The color key for keys in a properties file + * (value <code>"pf_coloring_key"</code>). + * + * @since 3.1 + */ + String PROPERTIES_FILE_COLORING_KEY= "pf_coloring_key"; //$NON-NLS-1$ + + /** + * The color key for comments in a properties file + * (value <code>"pf_coloring_comment"</code>). + * + * @since 3.1 + */ + + String PROPERTIES_FILE_COLORING_COMMENT= "pf_coloring_comment"; //$NON-NLS-1$ + + /** + * The color key for values in a properties file + * (value <code>"pf_coloring_value"</code>). + * + * @since 3.1 + */ + String PROPERTIES_FILE_COLORING_VALUE= "pf_coloring_value"; //$NON-NLS-1$ + + /** + * The color key for assignment in a properties file. + * (value <code>"pf_coloring_assignment"</code>). + * + * @since 3.1 + */ + String PROPERTIES_FILE_COLORING_ASSIGNMENT= "pf_coloring_assignment"; //$NON-NLS-1$ + + /** + * The color key for arguments in values in a properties file. + * (value <code>"pf_coloring_argument"</code>). + * + * @since 3.1 + */ + String PROPERTIES_FILE_COLORING_ARGUMENT= "pf_coloring_argument"; //$NON-NLS-1$ + + public static final String ANNOTATION="java_annotation"; //$NON-NLS-1$ +} diff --git a/demos/CodeEditor/src/application/text/IJavaPartitions.java b/demos/CodeEditor/src/application/text/IJavaPartitions.java new file mode 100644 index 000000000..e0047b899 --- /dev/null +++ b/demos/CodeEditor/src/application/text/IJavaPartitions.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package application.text; + +/** + * Definition of Java partitioning and its partitions. + * + * @since 3.1 + */ +public interface IJavaPartitions { + + /** + * The identifier of the Java partitioning. + */ + String JAVA_PARTITIONING= "___java_partitioning"; //$NON-NLS-1$ + + /** + * The identifier of the single-line (JLS2: EndOfLineComment) end comment partition content type. + */ + String JAVA_SINGLE_LINE_COMMENT= "__java_singleline_comment"; //$NON-NLS-1$ + + /** + * The identifier multi-line (JLS2: TraditionalComment) comment partition content type. + */ + String JAVA_MULTI_LINE_COMMENT= "__java_multiline_comment"; //$NON-NLS-1$ + + /** + * The identifier of the Javadoc (JLS2: DocumentationComment) partition content type. + */ + String JAVA_DOC= "__java_javadoc"; //$NON-NLS-1$ + + /** + * The identifier of the Java string partition content type. + */ + String JAVA_STRING= "__java_string"; //$NON-NLS-1$ + + /** + * The identifier of the Java character partition content type. + */ + String JAVA_CHARACTER= "__java_character"; //$NON-NLS-1$ +} diff --git a/demos/CodeEditor/src/application/text/JavaCodeScanner.java b/demos/CodeEditor/src/application/text/JavaCodeScanner.java new file mode 100644 index 000000000..09dec5868 --- /dev/null +++ b/demos/CodeEditor/src/application/text/JavaCodeScanner.java @@ -0,0 +1,374 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package application.text; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.rules.CombinedWordRule; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWhitespaceDetector; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; + +public class JavaCodeScanner extends AbstractJavaScanner { + private static final String INTERFACE= "interface"; //$NON-NLS-1$ + private static final String RETURN= "return"; //$NON-NLS-1$ + + private static String[] fgJava14Keywords= { "assert" }; //$NON-NLS-1$ + private static String[] fgJava15Keywords= { "enum" }; //$NON-NLS-1$ + + static String[] fgKeywords= { + "abstract", //$NON-NLS-1$ + "break", //$NON-NLS-1$ + "case", "catch", "class", "const", "continue", //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ + "default", "do", //$NON-NLS-2$ //$NON-NLS-1$ + "else", "extends", //$NON-NLS-2$ //$NON-NLS-1$ + "final", "finally", "for", //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ + "goto", //$NON-NLS-1$ + "if", "implements", "import", "instanceof", "interface", //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ + "native", "new", //$NON-NLS-2$ //$NON-NLS-1$ + "package", "private", "protected", "public", //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ + "static", "super", "switch", "synchronized", //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ + "this", "throw", "throws", "transient", "try", //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ + "volatile", //$NON-NLS-1$ + "while" //$NON-NLS-1$ + }; + + private static String[] fgTypes= { "void", "boolean", "char", "byte", "short", "strictfp", "int", "long", "float", "double" }; //$NON-NLS-1$ //$NON-NLS-5$ //$NON-NLS-7$ //$NON-NLS-6$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-2$ + private static String[] fgConstants= { "false", "null", "true" }; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ + + public JavaCodeScanner() { + initialize(); + } + +// @Override +// public IToken nextToken() { +// IToken nextToken = super.nextToken(); +// System.err.println("FIND TOKEN: " + nextToken.getData()); +// return nextToken; +// } + + @Override + protected List<IRule> createRules() { + List<IRule> rules= new ArrayList<IRule>(); + + Token token= getToken(IJavaColorConstants.JAVA_STRING); + rules.add(new SingleLineRule("'", "'", token, '\\')); //$NON-NLS-2$ //$NON-NLS-1$ + + Token defaultToken= getToken(IJavaColorConstants.JAVA_DEFAULT); + + // Add generic whitespace rule. + rules.add(new WhitespaceRule(new JavaWhitespaceDetector(), defaultToken)); + + token= getToken(IJavaColorConstants.ANNOTATION); + AnnotationRule atInterfaceRule= new AnnotationRule(getToken(IJavaColorConstants.JAVA_KEYWORD), token); + rules.add(atInterfaceRule); + + // Add word rule for new keywords, see bug 4077 + JavaWordDetector wordDetector= new JavaWordDetector(); + CombinedWordRule combinedWordRule= new CombinedWordRule(wordDetector, defaultToken); + + // Add rule for operators + token= getToken(IJavaColorConstants.JAVA_OPERATOR); + rules.add(new OperatorRule(token)); + + // Add rule for brackets + token= getToken(IJavaColorConstants.JAVA_BRACKET); + rules.add(new BracketRule(token)); + + // Add word rule for keyword 'return'. + CombinedWordRule.WordMatcher returnWordRule= new CombinedWordRule.WordMatcher(); + token= getToken(IJavaColorConstants.JAVA_KEYWORD_RETURN); + returnWordRule.addWord(RETURN, token); + combinedWordRule.addWordMatcher(returnWordRule); + + // Add word rule for keywords, types, and constants. + CombinedWordRule.WordMatcher wordRule= new CombinedWordRule.WordMatcher(); + token= getToken(IJavaColorConstants.JAVA_KEYWORD); + + for (int i=0; i<fgJava14Keywords.length; i++) + wordRule.addWord(fgJava14Keywords[i], token); + for (int i=0; i<fgJava15Keywords.length; i++) + wordRule.addWord(fgJava15Keywords[i], token); + for (int i=0; i<fgKeywords.length; i++) + wordRule.addWord(fgKeywords[i], token); + for (int i=0; i<fgTypes.length; i++) + wordRule.addWord(fgTypes[i], token); + for (int i=0; i<fgConstants.length; i++) + wordRule.addWord(fgConstants[i], token); + + combinedWordRule.addWordMatcher(wordRule); + + rules.add(combinedWordRule); + + setDefaultReturnToken(defaultToken); + return rules; + } + + /** + * An annotation rule matches the '@' symbol, any following whitespace and + * optionally a following <code>interface</code> keyword. + * + * It does not match if there is a comment between the '@' symbol and + * the identifier. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=82452 + * + * @since 3.1 + */ + private static class AnnotationRule implements IRule { + /** + * A resettable scanner supports marking a position in a scanner and + * unreading back to the marked position. + */ + private static final class ResettableScanner implements ICharacterScanner { + private final ICharacterScanner fDelegate; + private int fReadCount; + + /** + * Creates a new resettable scanner that will forward calls + * to <code>scanner</code>, but store a marked position. + * + * @param scanner the delegate scanner + */ + public ResettableScanner(final ICharacterScanner scanner) { + fDelegate= scanner; + mark(); + } + + /* + * @see org.eclipse.jface.text.rules.ICharacterScanner#getColumn() + */ + public int getColumn() { + return fDelegate.getColumn(); + } + + /* + * @see org.eclipse.jface.text.rules.ICharacterScanner#getLegalLineDelimiters() + */ + public char[][] getLegalLineDelimiters() { + return fDelegate.getLegalLineDelimiters(); + } + + /* + * @see org.eclipse.jface.text.rules.ICharacterScanner#read() + */ + public int read() { + int ch= fDelegate.read(); + if (ch != ICharacterScanner.EOF) + fReadCount++; + return ch; + } + + /* + * @see org.eclipse.jface.text.rules.ICharacterScanner#unread() + */ + public void unread() { + if (fReadCount > 0) + fReadCount--; + fDelegate.unread(); + } + + /** + * Marks an offset in the scanned content. + */ + public void mark() { + fReadCount= 0; + } + + /** + * Resets the scanner to the marked position. + */ + public void reset() { + while (fReadCount > 0) + unread(); + + while (fReadCount < 0) + read(); + } + } + + private final IWhitespaceDetector fWhitespaceDetector= new JavaWhitespaceDetector(); + private final IWordDetector fWordDetector= new JavaWordDetector(); + private final IToken fInterfaceToken; + private final IToken fAtToken; + + /** + * Creates a new rule. + * + * @param interfaceToken the token to return if + * <code>'@\s*interface'</code> is matched + * @param atToken the token to return if <code>'@'</code> + * is matched, but not <code>'@\s*interface'</code> + * @param version the lowest <code>JavaCore.COMPILER_SOURCE</code> + * version that this rule is enabled + * @param currentVersion the current + * <code>JavaCore.COMPILER_SOURCE</code> version + */ + public AnnotationRule(IToken interfaceToken, Token atToken) { + fInterfaceToken= interfaceToken; + fAtToken= atToken; + } + + /* + * @see org.eclipse.jface.text.rules.IRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner) + */ + public IToken evaluate(ICharacterScanner scanner) { + ResettableScanner resettable= new ResettableScanner(scanner); + if (resettable.read() == '@') + return readAnnotation(resettable); + + resettable.reset(); + return Token.UNDEFINED; + } + + private IToken readAnnotation(ResettableScanner scanner) { + scanner.mark(); + skipWhitespace(scanner); + if (readInterface(scanner)) { + return fInterfaceToken; + } else { + scanner.reset(); + return fAtToken; + } + } + + private boolean readInterface(ICharacterScanner scanner) { + int ch= scanner.read(); + int i= 0; + while (i < INTERFACE.length() && INTERFACE.charAt(i) == ch) { + i++; + ch= scanner.read(); + } + if (i < INTERFACE.length()) + return false; + + if (fWordDetector.isWordPart((char) ch)) + return false; + + if (ch != ICharacterScanner.EOF) + scanner.unread(); + + return true; + } + + private boolean skipWhitespace(ICharacterScanner scanner) { + while (fWhitespaceDetector.isWhitespace((char) scanner.read())) { + // do nothing + } + + scanner.unread(); + return true; + } + + } + + private static final class OperatorRule implements IRule { + + /** Java operators */ + private final char[] JAVA_OPERATORS= { ';', '.', '=', '/', '\\', '+', '-', '*', '<', '>', ':', '?', '!', ',', '|', '&', '^', '%', '~'}; + /** Token to return for this rule */ + private final IToken fToken; + + /** + * Creates a new operator rule. + * + * @param token Token to use for this rule + */ + public OperatorRule(IToken token) { + fToken= token; + } + + /** + * Is this character an operator character? + * + * @param character Character to determine whether it is an operator character + * @return <code>true</code> iff the character is an operator, <code>false</code> otherwise. + */ + public boolean isOperator(char character) { + for (int index= 0; index < JAVA_OPERATORS.length; index++) { + if (JAVA_OPERATORS[index] == character) + return true; + } + return false; + } + + /* + * @see org.eclipse.jface.text.rules.IRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner) + */ + public IToken evaluate(ICharacterScanner scanner) { + + int character= scanner.read(); + if (isOperator((char) character)) { + do { + character= scanner.read(); + } while (isOperator((char) character)); + scanner.unread(); + return fToken; + } else { + scanner.unread(); + return Token.UNDEFINED; + } + } + } + + private static final class BracketRule implements IRule { + + /** Java brackets */ + private final char[] JAVA_BRACKETS= { '(', ')', '{', '}', '[', ']' }; + /** Token to return for this rule */ + private final IToken fToken; + + /** + * Creates a new bracket rule. + * + * @param token Token to use for this rule + */ + public BracketRule(IToken token) { + fToken= token; + } + + /** + * Is this character a bracket character? + * + * @param character Character to determine whether it is a bracket character + * @return <code>true</code> iff the character is a bracket, <code>false</code> otherwise. + */ + public boolean isBracket(char character) { + for (int index= 0; index < JAVA_BRACKETS.length; index++) { + if (JAVA_BRACKETS[index] == character) + return true; + } + return false; + } + + /* + * @see org.eclipse.jface.text.rules.IRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner) + */ + public IToken evaluate(ICharacterScanner scanner) { + + int character= scanner.read(); + if (isBracket((char) character)) { + do { + character= scanner.read(); + } while (isBracket((char) character)); + scanner.unread(); + return fToken; + } else { + scanner.unread(); + return Token.UNDEFINED; + } + } + } +} diff --git a/demos/CodeEditor/src/application/text/JavaCommentScanner.java b/demos/CodeEditor/src/application/text/JavaCommentScanner.java new file mode 100644 index 000000000..fb8a27a52 --- /dev/null +++ b/demos/CodeEditor/src/application/text/JavaCommentScanner.java @@ -0,0 +1,188 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package application.text; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import org.eclipse.jface.text.rules.CombinedWordRule; +import org.eclipse.jface.text.rules.CombinedWordRule.CharacterBuffer; +import org.eclipse.jface.text.rules.CombinedWordRule.WordMatcher; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.Token; + +public class JavaCommentScanner extends AbstractJavaScanner { + protected static final String TASK_TAG= IJavaColorConstants.TASK_TAG; + private TaskTagMatcher fTaskTagMatcher; + private String fDefaultTokenProperty; +// private String[] fTokenProperties; + + public JavaCommentScanner(String defaultTokenProperty) { + this(defaultTokenProperty, new String[] { defaultTokenProperty, TASK_TAG }); + } + + public JavaCommentScanner(String defaultTokenProperty, String[] tokenProperties) { + fDefaultTokenProperty= defaultTokenProperty; +// fTokenProperties= tokenProperties; + initialize(); + } + + @Override + protected List<IRule> createRules() { + List<IRule> list= new ArrayList<IRule>(); + Token defaultToken= getToken(fDefaultTokenProperty); + + List<WordMatcher> matchers= createMatchers(); + if (matchers.size() > 0) { + CombinedWordRule combinedWordRule= new CombinedWordRule(new AtJavaIdentifierDetector(), defaultToken); + for (int i= 0, n= matchers.size(); i < n; i++) + combinedWordRule.addWordMatcher(matchers.get(i)); + list.add(combinedWordRule); + } + + setDefaultReturnToken(defaultToken); + + return list; + } + + protected List<WordMatcher> createMatchers() { + List<WordMatcher> list= new ArrayList<WordMatcher>(); + + // Add rule for Task Tags. + boolean isCaseSensitive= true; + String tasks= "TODO"; +// if (getPreferenceStore().contains(COMPILER_TASK_TAGS)) { +// tasks= getPreferenceStore().getString(COMPILER_TASK_TAGS); +// isCaseSensitive= ENABLED.equals(getPreferenceStore().getString(COMPILER_TASK_CASE_SENSITIVE)); +// } else if (fCorePreferenceStore != null) { +// tasks= fCorePreferenceStore.getString(COMPILER_TASK_TAGS); +// isCaseSensitive= ENABLED.equals(fCorePreferenceStore.getString(COMPILER_TASK_CASE_SENSITIVE)); +// } + if (tasks != null) { + fTaskTagMatcher= new TaskTagMatcher(getToken(TASK_TAG)); + fTaskTagMatcher.addTaskTags(tasks); + fTaskTagMatcher.setCaseSensitive(isCaseSensitive); + list.add(fTaskTagMatcher); + } + + return list; + } + + private class TaskTagMatcher extends CombinedWordRule.WordMatcher { + + private IToken fToken; + /** + * Uppercase words + * @since 3.0 + */ + private Map<CharacterBuffer, IToken> fUppercaseWords= new HashMap<CharacterBuffer, IToken>(); + /** + * <code>true</code> if task tag detection is case-sensitive. + * @since 3.0 + */ + private boolean fCaseSensitive= true; + /** + * Buffer for uppercase word + * @since 3.0 + */ + private CombinedWordRule.CharacterBuffer fBuffer= new CombinedWordRule.CharacterBuffer(16); + + public TaskTagMatcher(IToken token) { + fToken= token; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.CombinedWordRule.WordMatcher#clearWords() + * @since 3.0 + */ + @Override + public synchronized void clearWords() { + super.clearWords(); + fUppercaseWords.clear(); + } + + public synchronized void addTaskTags(String value) { + String[] tasks= split(value, ","); //$NON-NLS-1$ + for (int i= 0; i < tasks.length; i++) { + if (tasks[i].length() > 0) { + addWord(tasks[i], fToken); + } + } + } + + private String[] split(String value, String delimiters) { + StringTokenizer tokenizer= new StringTokenizer(value, delimiters); + int size= tokenizer.countTokens(); + String[] tokens= new String[size]; + int i= 0; + while (i < size) + tokens[i++]= tokenizer.nextToken(); + return tokens; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.CombinedWordRule.WordMatcher#addWord(java.lang.String, org.eclipse.jface.text.rules.IToken) + * @since 3.0 + */ + @Override + public synchronized void addWord(String word, IToken token) { + super.addWord(word, token); + fUppercaseWords.put(new CombinedWordRule.CharacterBuffer(word.toUpperCase()), token); + } + + /* + * @see org.eclipse.jdt.internal.ui.text.CombinedWordRule.WordMatcher#evaluate(org.eclipse.jface.text.rules.ICharacterScanner, org.eclipse.jdt.internal.ui.text.CombinedWordRule.CharacterBuffer) + * @since 3.0 + */ + @Override + public synchronized IToken evaluate(ICharacterScanner scanner, CombinedWordRule.CharacterBuffer word) { + if (fCaseSensitive) + return super.evaluate(scanner, word); + + fBuffer.clear(); + for (int i= 0, n= word.length(); i < n; i++) + fBuffer.append(Character.toUpperCase(word.charAt(i))); + + IToken token= fUppercaseWords.get(fBuffer); + if (token != null) + return token; + return Token.UNDEFINED; + } + + /** + * Enables/disables the case-sensitivity of the task tag detection. + * + * @param caseSensitive <code>true</code> iff case-sensitivity should be enabled + * @since 3.0 + */ + public void setCaseSensitive(boolean caseSensitive) { + fCaseSensitive= caseSensitive; + } + } + + private static class AtJavaIdentifierDetector implements IWordDetector { + + public boolean isWordStart(char c) { + return c == '@' || Character.isJavaIdentifierStart(c); + } + + public boolean isWordPart(char c) { + return c == '.' || Character.isJavaIdentifierPart(c); + } + } + +} diff --git a/demos/CodeEditor/src/application/text/JavaDocScanner.java b/demos/CodeEditor/src/application/text/JavaDocScanner.java new file mode 100644 index 000000000..e385a92d1 --- /dev/null +++ b/demos/CodeEditor/src/application/text/JavaDocScanner.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package application.text; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; +import org.eclipse.jface.text.rules.WordRule; + +public class JavaDocScanner extends JavaCommentScanner { + private static String[] fgTokenProperties= { + IJavaColorConstants.JAVADOC_KEYWORD, + IJavaColorConstants.JAVADOC_TAG, + IJavaColorConstants.JAVADOC_LINK, + IJavaColorConstants.JAVADOC_DEFAULT, + TASK_TAG + }; + + + public JavaDocScanner() { + super(IJavaColorConstants.JAVADOC_DEFAULT, fgTokenProperties); + } + + public IDocument getDocument() { + return fDocument; + } + + @Override + protected List<IRule> createRules() { + + List<IRule> list= new ArrayList<IRule>(); + + // Add rule for tags + Token token= getToken(IJavaColorConstants.JAVADOC_TAG); + list.add(new TagRule(token)); + + + // Add rule for HTML comments + WordRule wordRule= new WordRule(new HTMLCommentDetector(), token); + wordRule.addWord("<!--", token); //$NON-NLS-1$ + wordRule.addWord("--!>", token); //$NON-NLS-1$ + list.add(wordRule); + + + // Add rules for links + token= getToken(IJavaColorConstants.JAVADOC_LINK); + list.add(new MultiLineRule("{@link", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$ + list.add(new MultiLineRule("{@value", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$ + list.add(new MultiLineRule("{@inheritDoc", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$ + + // Add rules for @code and @literals + token= getToken(IJavaColorConstants.JAVADOC_DEFAULT); + list.add(new MultiLineRule("{@code", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$ + list.add(new MultiLineRule("{@literal", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$ + + // Add generic whitespace rule + token= getToken(IJavaColorConstants.JAVADOC_DEFAULT); + list.add(new WhitespaceRule(new JavaWhitespaceDetector(), token)); + + + list.addAll(super.createRules()); + return list; + } + + class TagRule extends SingleLineRule { + + /* + * @see SingleLineRule + */ + public TagRule(IToken token) { + super("<", ">", token, (char) 0); //$NON-NLS-2$ //$NON-NLS-1$ + } + + /* + * @see SingleLineRule + */ + public TagRule(IToken token, char escapeCharacter) { + super("<", ">", token, escapeCharacter); //$NON-NLS-2$ //$NON-NLS-1$ + } + + private IToken evaluateToken() { + try { + final String token= getDocument().get(getTokenOffset(), getTokenLength()) + "."; //$NON-NLS-1$ + + int offset= 0; + char character= token.charAt(++offset); + + if (character == '/') + character= token.charAt(++offset); + + while (Character.isWhitespace(character)) + character= token.charAt(++offset); + + while (Character.isLetterOrDigit(character)) + character= token.charAt(++offset); + + while (Character.isWhitespace(character)) + character= token.charAt(++offset); + + if (offset >= 2 && token.charAt(offset) == fEndSequence[0]) + return fToken; + + } catch (BadLocationException exception) { + // Do nothing + } + return getToken(IJavaColorConstants.JAVADOC_DEFAULT); + } + + /* + * @see PatternRule#evaluate(ICharacterScanner) + */ + @Override + public IToken evaluate(ICharacterScanner scanner) { + IToken result= super.evaluate(scanner); + if (result == fToken) + return evaluateToken(); + return result; + } + } + + static class HTMLCommentDetector implements IWordDetector { + + /** + * @see IWordDetector#isWordStart(char) + */ + public boolean isWordStart(char c) { + return (c == '<' || c == '-'); + } + + /** + * @see IWordDetector#isWordPart(char) + */ + public boolean isWordPart(char c) { + return (c == '-' || c == '!' || c == '>'); + } + } +} diff --git a/demos/CodeEditor/src/application/text/JavaSourceConfiguration.java b/demos/CodeEditor/src/application/text/JavaSourceConfiguration.java new file mode 100644 index 000000000..fd8e8d5f1 --- /dev/null +++ b/demos/CodeEditor/src/application/text/JavaSourceConfiguration.java @@ -0,0 +1,119 @@ +/******************************************************************************* +* Copyright (c) 2014 BestSolution.at and others. +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* Tom Schindl<tom.schindl@bestsolution.at> - initial API and implementation +*******************************************************************************/ +package application.text; + +import java.util.List; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.rules.ITokenScanner; +import org.eclipse.jface.text.source.AnnotationPresenter; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; + +public class JavaSourceConfiguration extends SourceViewerConfiguration { + + private JavaCodeScanner fCodeScanner; + private JavaDocScanner fJavaDocScanner; + private JavaCommentScanner fMultilineCommentScanner; + private JavaCommentScanner fSinglelineCommentScanner; + private SingleTokenJavaScanner fStringScanner; + private IAnnotationModel annotationModel; + private List<AnnotationPresenter> annotationPresenters; + + public JavaSourceConfiguration() { + initializeScanners(); + } + + @Override + public IAnnotationModel getAnnotationModel() { + return annotationModel; + } + + private void initializeScanners() { + fCodeScanner= new JavaCodeScanner(); + fMultilineCommentScanner= new JavaCommentScanner(IJavaColorConstants.JAVA_MULTI_LINE_COMMENT); + fSinglelineCommentScanner= new JavaCommentScanner(IJavaColorConstants.JAVA_SINGLE_LINE_COMMENT); + fStringScanner= new SingleTokenJavaScanner(IJavaColorConstants.JAVA_STRING); + fJavaDocScanner= new JavaDocScanner(); + } + + @Override + public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) { + return IJavaPartitions.JAVA_PARTITIONING; + } + + @Override + public IPresentationReconciler getPresentationReconciler( + ISourceViewer sourceViewer) { + PresentationReconciler reconciler= new /*JavaPresentationReconciler*/ PresentationReconciler(); + reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); + + DefaultDamagerRepairer dr= new DefaultDamagerRepairer(getCodeScanner()); + reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); + reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); + + dr= new DefaultDamagerRepairer(getJavaDocScanner()); + reconciler.setDamager(dr, IJavaPartitions.JAVA_DOC); + reconciler.setRepairer(dr, IJavaPartitions.JAVA_DOC); + + dr= new DefaultDamagerRepairer(getMultilineCommentScanner()); + reconciler.setDamager(dr, IJavaPartitions.JAVA_MULTI_LINE_COMMENT); + reconciler.setRepairer(dr, IJavaPartitions.JAVA_MULTI_LINE_COMMENT); + + dr= new DefaultDamagerRepairer(getSinglelineCommentScanner()); + reconciler.setDamager(dr, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT); + reconciler.setRepairer(dr, IJavaPartitions.JAVA_SINGLE_LINE_COMMENT); + + dr= new DefaultDamagerRepairer(getStringScanner()); + reconciler.setDamager(dr, IJavaPartitions.JAVA_STRING); + reconciler.setRepairer(dr, IJavaPartitions.JAVA_STRING); + + dr= new DefaultDamagerRepairer(getStringScanner()); + reconciler.setDamager(dr, IJavaPartitions.JAVA_CHARACTER); + reconciler.setRepairer(dr, IJavaPartitions.JAVA_CHARACTER); + + return reconciler; + } + + private ITokenScanner getStringScanner() { + return fStringScanner; + } + + private ITokenScanner getSinglelineCommentScanner() { + return fSinglelineCommentScanner; + } + + private ITokenScanner getMultilineCommentScanner() { + return fMultilineCommentScanner; + } + + private ITokenScanner getJavaDocScanner() { + return fJavaDocScanner; + } + + private ITokenScanner getCodeScanner() { + return fCodeScanner; + } + + @Override + public String getStyleclassName() { + return "java"; + } + + @Override + public List<AnnotationPresenter> getAnnotationPresenters() { + return annotationPresenters; + } +}
\ No newline at end of file diff --git a/demos/CodeEditor/src/application/text/JavaWhitespaceDetector.java b/demos/CodeEditor/src/application/text/JavaWhitespaceDetector.java new file mode 100644 index 000000000..ed276a0a4 --- /dev/null +++ b/demos/CodeEditor/src/application/text/JavaWhitespaceDetector.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package application.text; + +import org.eclipse.jface.text.rules.IWhitespaceDetector; + + +/** + * A java aware white space detector. + */ +public class JavaWhitespaceDetector implements IWhitespaceDetector { + + public boolean isWhitespace(char c) { + return Character.isWhitespace(c); + } + +} diff --git a/demos/CodeEditor/src/application/text/JavaWordDetector.java b/demos/CodeEditor/src/application/text/JavaWordDetector.java new file mode 100644 index 000000000..d550d1114 --- /dev/null +++ b/demos/CodeEditor/src/application/text/JavaWordDetector.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package application.text; + + +import org.eclipse.jface.text.rules.IWordDetector; + +/** + * A Java aware word detector. + */ +public class JavaWordDetector implements IWordDetector { + + /* + * @see IWordDetector#isWordStart + */ + public boolean isWordStart(char c) { + return Character.isJavaIdentifierStart(c); + } + + /* + * @see IWordDetector#isWordPart + */ + public boolean isWordPart(char c) { + return Character.isJavaIdentifierPart(c); + } +} diff --git a/demos/CodeEditor/src/application/text/SingleTokenJavaScanner.java b/demos/CodeEditor/src/application/text/SingleTokenJavaScanner.java new file mode 100644 index 000000000..13cc896a6 --- /dev/null +++ b/demos/CodeEditor/src/application/text/SingleTokenJavaScanner.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package application.text; + +import java.util.List; + +import org.eclipse.jface.text.rules.IRule; + +public class SingleTokenJavaScanner extends AbstractJavaScanner{ + private String[] fProperty; + + public SingleTokenJavaScanner(String property) { + super(); + fProperty= new String[] { property }; + initialize(); + } + + @Override + protected List<IRule> createRules() { + setDefaultReturnToken(getToken(fProperty[0])); + return null; + } + +} |