Bug 574748: [Text-UI] Add FixTokenScanner
Change-Id: Iea9aa813fa0729317963afbc74fc5aa3c0b1b6e5
diff --git a/ltk/org.eclipse.statet.ltk.ui/src/org/eclipse/statet/ecommons/text/ui/presentation/FixTokenScanner.java b/ltk/org.eclipse.statet.ltk.ui/src/org/eclipse/statet/ecommons/text/ui/presentation/FixTokenScanner.java
new file mode 100644
index 0000000..9097d79
--- /dev/null
+++ b/ltk/org.eclipse.statet.ltk.ui/src/org/eclipse/statet/ecommons/text/ui/presentation/FixTokenScanner.java
@@ -0,0 +1,120 @@
+/*=============================================================================#
+ # Copyright (c) 2021 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.ecommons.text.ui.presentation;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.ITokenScanner;
+import org.eclipse.jface.text.rules.Token;
+
+import org.eclipse.statet.jcommons.collections.ImCollections;
+import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+
+@NonNullByDefault
+public class FixTokenScanner implements ITokenScanner {
+
+
+ private final TextStyleManager textStyles;
+ private final IToken defaultToken;
+
+ private ImList<ITypedRegion> styleRegions;
+
+ private int documentStartOffset;
+ private int documentEndOffset;
+
+ private int regionIdx;
+
+ private int tokenOffset;
+ private int tokenLength;
+
+
+ public FixTokenScanner(final TextStyleManager textStyles, final String defaultTokenKey) {
+ this.textStyles= textStyles;
+ this.defaultToken= textStyles.getToken(defaultTokenKey);
+
+ this.styleRegions= ImCollections.emptyList();
+ }
+
+
+ public void setStyleRegions(final ImList<ITypedRegion> regions) {
+ this.styleRegions= regions;
+ this.regionIdx= 0;
+ }
+
+
+ @Override
+ public void setRange(final IDocument document, final int offset, final int length) {
+ this.documentStartOffset= offset;
+ this.documentEndOffset= length;
+
+ this.regionIdx= 0;
+ this.tokenOffset= offset;
+ this.tokenLength= 0;
+ }
+
+ @Override
+ public IToken nextToken() {
+ this.tokenOffset+= this.tokenLength;
+
+ if (this.tokenOffset == this.documentEndOffset) {
+ return Token.EOF;
+ }
+
+ final ITypedRegion region= nextRegion();
+ if (region != null) {
+ if (this.tokenOffset >= region.getOffset()) {
+ setTokenEndOffset(region.getOffset() + region.getLength());
+ return this.textStyles.getToken(region.getType());
+ }
+ setTokenEndOffset(region.getOffset());
+ return this.defaultToken;
+ }
+ else {
+ setTokenEndOffset(Integer.MAX_VALUE);
+ return this.defaultToken;
+ }
+ }
+
+ private @Nullable ITypedRegion nextRegion() {
+ for (int idx= this.regionIdx; idx < this.styleRegions.size(); idx++) {
+ final ITypedRegion region= this.styleRegions.get(idx);
+ if (this.tokenOffset < region.getOffset() + region.getLength()) {
+ this.regionIdx= idx;
+ return region;
+ }
+ }
+ return null;
+ }
+
+ private void setTokenEndOffset(final int offset) {
+ this.tokenLength= Math.min(offset, this.documentEndOffset) - this.tokenOffset;
+ }
+
+ @Override
+ public int getTokenOffset() {
+ return this.tokenOffset;
+ }
+
+ @Override
+ public int getTokenLength() {
+ return this.tokenLength;
+ }
+
+
+}