diff --git a/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/UserDefinedJavaClassDialog.java b/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/UserDefinedJavaClassDialog.java index 716b9e8132..4f60f4baa5 100644 --- a/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/UserDefinedJavaClassDialog.java +++ b/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/UserDefinedJavaClassDialog.java @@ -318,6 +318,7 @@ public String open() { wlPosition.setLayoutData(fdlPosition); folder = new CTabFolder(wTop, SWT.BORDER | SWT.RESIZE); + PropsUi.setLook(folder, Props.WIDGET_STYLE_TAB); folder.setUnselectedImageVisible(true); folder.setUnselectedCloseVisible(true); FormData fdScript = new FormData(); diff --git a/plugins/transforms/tableinput/src/main/java/org/apache/hop/pipeline/transforms/tableinput/TableInputDialog.java b/plugins/transforms/tableinput/src/main/java/org/apache/hop/pipeline/transforms/tableinput/TableInputDialog.java index d4d7852b49..a1c3dabd29 100644 --- a/plugins/transforms/tableinput/src/main/java/org/apache/hop/pipeline/transforms/tableinput/TableInputDialog.java +++ b/plugins/transforms/tableinput/src/main/java/org/apache/hop/pipeline/transforms/tableinput/TableInputDialog.java @@ -357,12 +357,12 @@ public void mouseUp(MouseEvent e) { private List getSqlReservedWords() { // Do not search keywords when connection is empty if (input.getConnection() == null || input.getConnection().isEmpty()) { - return new ArrayList<>(); + return List.of(); } // If connection is a variable that can't be resolved if (variables.resolve(input.getConnection()).startsWith("${")) { - return new ArrayList<>(); + return List.of(); } DatabaseMeta databaseMeta = pipelineMeta.findDatabase(input.getConnection(), variables); @@ -370,11 +370,10 @@ private List getSqlReservedWords() { logError("Database connection not found. Proceding without keywords."); return new ArrayList<>(); } - Database db = new Database(loggingObject, variables, databaseMeta); - DatabaseMetaData databaseMetaData = null; - try { + + try (Database db = new Database(loggingObject, variables, databaseMeta)) { db.connect(); - databaseMetaData = db.getDatabaseMetaData(); + DatabaseMetaData databaseMetaData = db.getDatabaseMetaData(); if (databaseMetaData == null) { logError("Couldn't get database metadata"); return new ArrayList<>(); @@ -392,10 +391,7 @@ private List getSqlReservedWords() { return sqlKeywords; } catch (HopDatabaseException e) { logError("Couldn't extract keywords from database metadata. Proceding without them."); - return new ArrayList<>(); - } finally { - db.disconnect(); - db.close(); + return List.of(); } } diff --git a/ui/src/main/java/org/apache/hop/ui/core/widget/JavaScriptStyledTextComp.java b/ui/src/main/java/org/apache/hop/ui/core/widget/JavaScriptStyledTextComp.java index 61d50dd3d6..2aa394043d 100644 --- a/ui/src/main/java/org/apache/hop/ui/core/widget/JavaScriptStyledTextComp.java +++ b/ui/src/main/java/org/apache/hop/ui/core/widget/JavaScriptStyledTextComp.java @@ -49,7 +49,7 @@ public void addLineStyleListener() { } @Override - public void addLineStyleListener(List keywords) { - addLineStyleListener(new JavaScriptHighlight()); + public void addLineStyleListener(List functionNames) { + addLineStyleListener(new JavaScriptHighlight(functionNames)); } } diff --git a/ui/src/main/java/org/apache/hop/ui/core/widget/SQLStyledTextComp.java b/ui/src/main/java/org/apache/hop/ui/core/widget/SQLStyledTextComp.java index 46a61f4b86..aa76ee85fa 100644 --- a/ui/src/main/java/org/apache/hop/ui/core/widget/SQLStyledTextComp.java +++ b/ui/src/main/java/org/apache/hop/ui/core/widget/SQLStyledTextComp.java @@ -19,7 +19,26 @@ import java.util.List; import org.apache.hop.core.variables.IVariables; -import org.apache.hop.ui.core.widget.highlight.SQLValuesHighlight; +import org.apache.hop.i18n.BaseMessages; +import org.apache.hop.ui.core.ConstUi; +import org.apache.hop.ui.core.FormDataBuilder; +import org.apache.hop.ui.core.PropsUi; +import org.apache.hop.ui.core.gui.GuiResource; +import org.apache.hop.ui.core.widget.highlight.SqlHighlight; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.LineStyleListener; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Composite; public class SQLStyledTextComp extends StyledTextVar { @@ -44,11 +63,11 @@ public SQLStyledTextComp( @Override public void addLineStyleListener() { - addLineStyleListener(new SQLValuesHighlight(List.of())); + addLineStyleListener(new SqlHighlight(List.of())); } @Override public void addLineStyleListener(List keywords) { - addLineStyleListener(new SQLValuesHighlight(keywords)); + addLineStyleListener(new SqlHighlight(keywords)); } } diff --git a/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/GenericCodeHighlight.java b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/GenericCodeHighlight.java index 231739933e..7bc40acb04 100644 --- a/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/GenericCodeHighlight.java +++ b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/GenericCodeHighlight.java @@ -20,24 +20,23 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; -import java.util.Hashtable; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Vector; +import org.apache.hop.core.util.Utils; +import org.apache.hop.ui.core.PropsUi; import org.apache.hop.ui.core.gui.GuiResource; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.LineStyleEvent; import org.eclipse.swt.custom.LineStyleListener; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; -import org.eclipse.swt.graphics.Color; public class GenericCodeHighlight implements LineStyleListener { CodeScanner scanner; - int[] tokenColors; - Color[] colors; - Vector blockComments = new Vector<>(); + StyleAttribute[] styleAttributes; + ArrayList blockComments = new ArrayList<>(); public static final int EOF = -1; public static final int EOL = 10; @@ -46,30 +45,31 @@ public class GenericCodeHighlight implements LineStyleListener { public static final int WHITE = 1; public static final int KEY = 2; public static final int COMMENT = 3; // single line comment: // + public static final int SYMBOL = 4; public static final int STRING = 5; public static final int OTHER = 6; public static final int NUMBER = 7; - public static final int FUNCTIONS = 8; + public static final int FUNCTION = 8; public static final int MAXIMUM_TOKEN = 9; public GenericCodeHighlight(ScriptEngine engine) { - initializeColors(); + initializeStyles(); scanner = new CodeScanner(engine.getKeywords(), engine.getBuiltInFunctions()); - scanner.setKeywords(engine.getKeywords()); - scanner.setFunctions(engine.getBuiltInFunctions()); + scanner.addKeywords(engine.getKeywords()); + scanner.addFunctionNames(engine.getBuiltInFunctions()); } - Color getColor(int type) { - if (type < 0 || type >= tokenColors.length) { + StyleAttribute getStyleAttribute(int type) { + if (type < 0 || type >= styleAttributes.length) { return null; } - return colors[tokenColors[type]]; + return styleAttributes[type]; } boolean inBlockComment(int start, int end) { for (int i = 0; i < blockComments.size(); i++) { - int[] offsets = blockComments.elementAt(i); + int[] offsets = blockComments.get(i); // start of comment in the line if ((offsets[0] >= start) && (offsets[0] <= end)) { return true; @@ -85,30 +85,24 @@ boolean inBlockComment(int start, int end) { return false; } - void initializeColors() { - final GuiResource guiResource = GuiResource.getInstance(); - colors = - new Color[] { - guiResource.getColorBlack(), - guiResource.getColorRed(), - guiResource.getColorDarkGreen(), - guiResource.getColorBlue(), - guiResource.getColorOrange() - }; - tokenColors = new int[MAXIMUM_TOKEN]; - tokenColors[WORD] = 0; - tokenColors[WHITE] = 0; - tokenColors[KEY] = 3; - tokenColors[COMMENT] = 1; - tokenColors[STRING] = 2; - tokenColors[OTHER] = 0; - tokenColors[NUMBER] = 0; - tokenColors[FUNCTIONS] = 4; - } - - void disposeColors() { - for (int i = 0; i < colors.length; i++) { - colors[i].dispose(); + void initializeStyles() { + GuiResource resource = GuiResource.getInstance(); + styleAttributes = new StyleAttribute[MAXIMUM_TOKEN]; + styleAttributes[WORD] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[WHITE] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[STRING] = new StyleAttribute(resource.getColorDarkGreen(), SWT.NORMAL); + styleAttributes[OTHER] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[NUMBER] = new StyleAttribute(resource.getColorOrange(), SWT.NORMAL); + if (PropsUi.getInstance().isDarkMode()) { + styleAttributes[COMMENT] = new StyleAttribute(resource.getColorGray(), SWT.ITALIC); + styleAttributes[KEY] = new StyleAttribute(resource.getColor(30, 144, 255), SWT.NORMAL); + styleAttributes[SYMBOL] = new StyleAttribute(resource.getColor(243, 126, 131), SWT.NORMAL); + styleAttributes[FUNCTION] = new StyleAttribute(resource.getColor(177, 102, 218), SWT.NORMAL); + } else { + styleAttributes[COMMENT] = new StyleAttribute(resource.getColorDarkGray(), SWT.ITALIC); + styleAttributes[KEY] = new StyleAttribute(resource.getColorBlue(), SWT.NORMAL); + styleAttributes[SYMBOL] = new StyleAttribute(resource.getColorDarkRed(), SWT.NORMAL); + styleAttributes[FUNCTION] = new StyleAttribute(resource.getColor(148, 0, 211), SWT.NORMAL); } } @@ -118,15 +112,19 @@ void disposeColors() { * background color (output) */ public void lineGetStyle(LineStyleEvent event) { - Vector styles = new Vector<>(); - int token; + ArrayList styles = new ArrayList<>(); StyleRange lastStyle; if (inBlockComment(event.lineOffset, event.lineOffset + event.lineText.length())) { - styles.addElement( - new StyleRange(event.lineOffset, event.lineText.length() + 4, colors[2], null)); - event.styles = new StyleRange[styles.size()]; - styles.copyInto(event.styles); + StyleAttribute attribute = getStyleAttribute(COMMENT); + styles.add( + new StyleRange( + event.lineOffset, + event.lineText.length() + 4, + attribute.getForeground(), + null, + attribute.getStyle())); + event.styles = styles.toArray(new StyleRange[styles.size()]); return; } scanner.setRange(event.lineText); @@ -134,12 +132,12 @@ public void lineGetStyle(LineStyleEvent event) { if (xs != null) { parseBlockComments(xs); } - token = scanner.nextToken(); + int token = scanner.nextToken(); while (token != EOF) { if (token != OTHER) { if ((token == WHITE) && (!styles.isEmpty())) { int start = scanner.getStartOffset() + event.lineOffset; - lastStyle = styles.lastElement(); + lastStyle = styles.get(styles.size() - 1); if (lastStyle.fontStyle != SWT.NORMAL) { if (lastStyle.start + lastStyle.length == start) { // have the white space take on the style before it to minimize font style @@ -148,23 +146,27 @@ public void lineGetStyle(LineStyleEvent event) { } } } else { - Color color = getColor(token); - if (color != colors[0]) { // hardcoded default foreground color, black + StyleAttribute attribute = getStyleAttribute(token); + if (attribute != styleAttributes[0]) { // hardcoded default foreground color, black StyleRange style = new StyleRange( - scanner.getStartOffset() + event.lineOffset, scanner.getLength(), color, null); + scanner.getStartOffset() + event.lineOffset, + scanner.getLength(), + attribute.getForeground(), + null, + attribute.getStyle()); if (token == KEY) { style.fontStyle = SWT.BOLD; } if (styles.isEmpty()) { - styles.addElement(style); + styles.add(style); } else { - lastStyle = styles.lastElement(); + lastStyle = styles.get(styles.size() - 1); if (lastStyle.similarTo(style) && (lastStyle.start + lastStyle.length == style.start)) { lastStyle.length += style.length; } else { - styles.addElement(style); + styles.add(style); } } } @@ -172,12 +174,11 @@ public void lineGetStyle(LineStyleEvent event) { } token = scanner.nextToken(); } - event.styles = new StyleRange[styles.size()]; - styles.copyInto(event.styles); + event.styles = styles.toArray(new StyleRange[styles.size()]); } public void parseBlockComments(String text) { - blockComments = new Vector<>(); + blockComments = new ArrayList<>(); StringReader buffer = new StringReader(text); int ch; boolean blkComment = false; @@ -192,7 +193,7 @@ public void parseBlockComments(String text) { { if (blkComment) { offsets[1] = cnt; - blockComments.addElement(offsets); + blockComments.add(offsets); } done = true; break; @@ -219,7 +220,7 @@ public void parseBlockComments(String text) { if (ch == '/') { blkComment = false; offsets[1] = cnt; - blockComments.addElement(offsets); + blockComments.add(offsets); } } cnt++; @@ -240,10 +241,8 @@ public void parseBlockComments(String text) { /** A simple fuzzy scanner for Java */ public class CodeScanner { - protected Map fgKeys = null; - protected Map fgFunctions = null; - protected Map kfKeys = null; - protected Map kfFunctions = null; + protected Map reservedKeywords = new HashMap<>(); + protected Map reservedFunctionNames = new HashMap<>(); protected StringBuilder fBuffer = new StringBuilder(); protected String fDoc; protected int fPos; @@ -251,15 +250,9 @@ public class CodeScanner { protected int fStartToken; protected boolean fEofSeen = false; - private List kfKeywords = new ArrayList<>(); - - private List fgKeywords = new ArrayList<>(); - public CodeScanner(List keywords, List functions) { - this.setKeywords(keywords); - this.setFunctions(functions); - initialize(); - initializeETLFunctions(); + this.addKeywords(keywords); + this.addFunctionNames(functions); } /** Returns the ending location of the current token in the document. */ @@ -267,29 +260,18 @@ public final int getLength() { return fPos - fStartToken; } - /** Initialize the lookup table. */ - void initialize() { - fgKeys = new Hashtable<>(); - Integer k = Integer.valueOf(KEY); - for (int i = 0; i < fgKeywords.size(); i++) { - fgKeys.put(fgKeywords.get(i), k); + public void addKeywords(List reservedWords) { + if (Utils.isEmpty(reservedWords)) { + return; } + reservedWords.forEach(name -> reservedKeywords.put(name, Integer.valueOf(KEY))); } - public void setKeywords(List kfKeywords) { - this.kfKeywords = kfKeywords; - } - - public void setFunctions(List functions) { - this.fgKeywords = functions; - } - - void initializeETLFunctions() { - kfKeys = new Hashtable<>(); - Integer k = Integer.valueOf(FUNCTIONS); - for (int i = 0; i < kfKeywords.size(); i++) { - kfKeys.put(kfKeywords.get(i), k); + public void addFunctionNames(List functionNames) { + if (Utils.isEmpty(functionNames)) { + return; } + functionNames.forEach(name -> reservedFunctionNames.put(name, Integer.valueOf(FUNCTION))); } /** Returns the starting location of the current token in the document. */ @@ -374,13 +356,14 @@ public int nextToken() { c = read(); } while (Character.isJavaIdentifierPart((char) c)); unread(c); - Integer i = fgKeys.get(fBuffer.toString()); - if (i != null) { - return i.intValue(); + String name = fBuffer.toString(); + Integer token = reservedKeywords.get(name); + if (token != null) { + return token.intValue(); } - i = kfKeys.get(fBuffer.toString()); - if (i != null) { - return i.intValue(); + token = reservedFunctionNames.get(name); + if (token != null) { + return token.intValue(); } return WORD; } diff --git a/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/JavaHighlight.java b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/JavaHighlight.java index fef00d1339..b350f514b9 100644 --- a/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/JavaHighlight.java +++ b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/JavaHighlight.java @@ -19,22 +19,22 @@ import java.io.IOException; import java.io.StringReader; -import java.util.Hashtable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.Vector; +import org.apache.hop.ui.core.PropsUi; import org.apache.hop.ui.core.gui.GuiResource; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.LineStyleEvent; import org.eclipse.swt.custom.LineStyleListener; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; -import org.eclipse.swt.graphics.Color; public class JavaHighlight implements LineStyleListener { JavaScanner scanner = new JavaScanner(); - int[] tokenColors; - Color[] colors; - Vector blockComments = new Vector<>(); + StyleAttribute[] styleAttributes; + ArrayList blockComments = new ArrayList<>(); public static final int EOF = -1; public static final int EOL = 10; @@ -43,29 +43,50 @@ public class JavaHighlight implements LineStyleListener { public static final int WHITE = 1; public static final int KEY = 2; public static final int COMMENT = 3; // single line comment: // + public static final int SYMBOL = 4; public static final int STRING = 5; public static final int OTHER = 6; public static final int NUMBER = 7; - public static final int FUNCTIONS = 8; + public static final int FUNCTION = 8; public static final int MAXIMUM_TOKEN = 9; public JavaHighlight() { - initializeColors(); + initializeStyles(); scanner = new JavaScanner(); - scanner.initializeUDJCFunctions(); } - Color getColor(int type) { - if (type < 0 || type >= tokenColors.length) { + void initializeStyles() { + GuiResource resource = GuiResource.getInstance(); + styleAttributes = new StyleAttribute[MAXIMUM_TOKEN]; + styleAttributes[WORD] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[WHITE] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[STRING] = new StyleAttribute(resource.getColorDarkGreen(), SWT.NORMAL); + styleAttributes[OTHER] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[NUMBER] = new StyleAttribute(resource.getColorOrange(), SWT.NORMAL); + if (PropsUi.getInstance().isDarkMode()) { + styleAttributes[COMMENT] = new StyleAttribute(resource.getColorGray(), SWT.ITALIC); + styleAttributes[KEY] = new StyleAttribute(resource.getColor(30, 144, 255), SWT.NORMAL); + styleAttributes[SYMBOL] = new StyleAttribute(resource.getColor(243, 126, 131), SWT.NORMAL); + styleAttributes[FUNCTION] = new StyleAttribute(resource.getColor(177, 102, 218), SWT.NORMAL); + } else { + styleAttributes[COMMENT] = new StyleAttribute(resource.getColorDarkGray(), SWT.ITALIC); + styleAttributes[KEY] = new StyleAttribute(resource.getColorBlue(), SWT.NORMAL); + styleAttributes[SYMBOL] = new StyleAttribute(resource.getColorDarkRed(), SWT.NORMAL); + styleAttributes[FUNCTION] = new StyleAttribute(resource.getColor(148, 0, 211), SWT.NORMAL); + } + } + + StyleAttribute getStyleAttribute(int type) { + if (type < 0 || type >= styleAttributes.length) { return null; } - return colors[tokenColors[type]]; + return styleAttributes[type]; } boolean inBlockComment(int start, int end) { for (int i = 0; i < blockComments.size(); i++) { - int[] offsets = blockComments.elementAt(i); + int[] offsets = blockComments.get(i); // start of comment in the line if ((offsets[0] >= start) && (offsets[0] <= end)) { return true; @@ -81,41 +102,25 @@ boolean inBlockComment(int start, int end) { return false; } - void initializeColors() { - colors = - new Color[] { - GuiResource.getInstance().getColorBlack(), // black - GuiResource.getInstance().getColorRed(), // red - GuiResource.getInstance().getColorDarkGreen(), // green - GuiResource.getInstance().getColorBlue(), // blue - GuiResource.getInstance().getColorOrange() // orange - }; - tokenColors = new int[MAXIMUM_TOKEN]; - tokenColors[WORD] = 0; - tokenColors[WHITE] = 0; - tokenColors[KEY] = 3; - tokenColors[COMMENT] = 1; - tokenColors[STRING] = 2; - tokenColors[OTHER] = 0; - tokenColors[NUMBER] = 0; - tokenColors[FUNCTIONS] = 4; - } - /** * Event.detail line start offset (input) Event.text line text (input) LineStyleEvent.styles * Enumeration of StyleRanges, need to be in order. (output) LineStyleEvent.background line * background color (output) */ public void lineGetStyle(LineStyleEvent event) { - Vector styles = new Vector<>(); - int token; + ArrayList styles = new ArrayList<>(); StyleRange lastStyle; if (inBlockComment(event.lineOffset, event.lineOffset + event.lineText.length())) { - styles.addElement( - new StyleRange(event.lineOffset, event.lineText.length() + 4, colors[2], null)); - event.styles = new StyleRange[styles.size()]; - styles.copyInto(event.styles); + StyleAttribute attribute = getStyleAttribute(COMMENT); + styles.add( + new StyleRange( + event.lineOffset, + event.lineText.length() + 4, + attribute.getForeground(), + null, + attribute.getStyle())); + event.styles = styles.toArray(new StyleRange[styles.size()]); return; } scanner.setRange(event.lineText); @@ -123,12 +128,12 @@ public void lineGetStyle(LineStyleEvent event) { if (xs != null) { parseBlockComments(xs); } - token = scanner.nextToken(); + int token = scanner.nextToken(); while (token != EOF) { if (token != OTHER) { if ((token == WHITE) && (!styles.isEmpty())) { int start = scanner.getStartOffset() + event.lineOffset; - lastStyle = styles.lastElement(); + lastStyle = styles.get(styles.size() - 1); if (lastStyle.fontStyle != SWT.NORMAL) { if (lastStyle.start + lastStyle.length == start) { // have the white space take on the style before it to minimize font style @@ -137,23 +142,27 @@ public void lineGetStyle(LineStyleEvent event) { } } } else { - Color color = getColor(token); - if (color != colors[0]) { // hardcoded default foreground color, black + StyleAttribute attribute = getStyleAttribute(token); + if (attribute != styleAttributes[0]) { // hardcoded default foreground color, black StyleRange style = new StyleRange( - scanner.getStartOffset() + event.lineOffset, scanner.getLength(), color, null); + scanner.getStartOffset() + event.lineOffset, + scanner.getLength(), + attribute.getForeground(), + null, + attribute.getStyle()); if (token == KEY) { style.fontStyle = SWT.BOLD; } if (styles.isEmpty()) { - styles.addElement(style); + styles.add(style); } else { - lastStyle = styles.lastElement(); + lastStyle = styles.get(styles.size() - 1); if (lastStyle.similarTo(style) && (lastStyle.start + lastStyle.length == style.start)) { lastStyle.length += style.length; } else { - styles.addElement(style); + styles.add(style); } } } @@ -161,12 +170,11 @@ public void lineGetStyle(LineStyleEvent event) { } token = scanner.nextToken(); } - event.styles = new StyleRange[styles.size()]; - styles.copyInto(event.styles); + event.styles = styles.toArray(new StyleRange[styles.size()]); } public void parseBlockComments(String text) { - blockComments = new Vector<>(); + blockComments = new ArrayList<>(); StringReader buffer = new StringReader(text); int ch; boolean blkComment = false; @@ -181,7 +189,7 @@ public void parseBlockComments(String text) { { if (blkComment) { offsets[1] = cnt; - blockComments.addElement(offsets); + blockComments.add(offsets); } done = true; break; @@ -208,7 +216,7 @@ public void parseBlockComments(String text) { if (ch == '/') { blkComment = false; offsets[1] = cnt; - blockComments.addElement(offsets); + blockComments.add(offsets); } } cnt++; @@ -229,10 +237,7 @@ public void parseBlockComments(String text) { /** A simple fuzzy scanner for Java */ public class JavaScanner { - protected Map fgKeys = null; - protected Map fgFunctions = null; - protected Map kfKeys = null; - protected Map kfFunctions = null; + protected Map reserved = new HashMap<>(); protected StringBuilder fBuffer = new StringBuilder(); protected String fDoc; protected int fPos; @@ -241,8 +246,8 @@ public class JavaScanner { protected boolean fEofSeen = false; public JavaScanner() { - initialize(); - initializeUDJCFunctions(); + JAVA_KEYWORDS.forEach(name -> reserved.put(name, Integer.valueOf(KEY))); + UDJC_FUNCTIONS.forEach(name -> reserved.put(name, Integer.valueOf(FUNCTION))); } /** Returns the ending location of the current token in the document. */ @@ -250,23 +255,6 @@ public final int getLength() { return fPos - fStartToken; } - /** Initialize the lookup table. */ - void initialize() { - fgKeys = new Hashtable<>(); - Integer k = Integer.valueOf(KEY); - for (int i = 0; i < JAVA_KEYWORDS.length; i++) { - fgKeys.put(JAVA_KEYWORDS[i], k); - } - } - - void initializeUDJCFunctions() { - kfKeys = new Hashtable<>(); - Integer k = Integer.valueOf(FUNCTIONS); - for (int i = 0; i < UDJC_FUNCTIONS.length; i++) { - kfKeys.put(UDJC_FUNCTIONS[i], k); - } - } - /** Returns the starting location of the current token in the document. */ public final int getStartOffset() { return fStartToken; @@ -328,6 +316,28 @@ public int nextToken() { } } + case '(', + ')', + '{', + '}', + '[', + ']', + '*', + '+', + '-', + '=', + '>', + '<', + '!', + ':', + '.', + ',', + ';', + '&', + '|', + '^': + return SYMBOL; + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': do { c = read(); @@ -349,13 +359,10 @@ public int nextToken() { c = read(); } while (Character.isJavaIdentifierPart((char) c)); unread(c); - Integer i = fgKeys.get(fBuffer.toString()); - if (i != null) { - return i.intValue(); - } - i = kfKeys.get(fBuffer.toString()); - if (i != null) { - return i.intValue(); + String name = fBuffer.toString(); + Integer token = reserved.get(name); + if (token != null) { + return token.intValue(); } return WORD; } @@ -385,168 +392,168 @@ protected void unread(int c) { } } - private static final String[] JAVA_KEYWORDS = { - "abstract", - "assert", - "boolean", - "break", - "byte", - "case", - "catch", - "char", - "class", - "const", - "continue", - "default", - "do", - "double", - "else", - "enum", - "extends", - "final", - "finally", - "float", - "for", - "goto", - "if", - "implements", - "import", - "instanceof", - "int", - "interface", - "long", - "native", - "new", - "package", - "private", - "protected", - "public", - "return", - "short", - "static", - "strictfp", - "super", - "switch", - "synchronized", - "this", - "throw", - "throws", - "transient", - "try", - "void", - "volatile", - "while", - }; + private static final List JAVA_KEYWORDS = + List.of( + "abstract", + "assert", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "default", + "do", + "double", + "else", + "enum", + "extends", + "final", + "finally", + "float", + "for", + "goto", + "if", + "implements", + "import", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "strictfp", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "try", + "void", + "volatile", + "while"); // built from TransformClassBase.java with the following Vim commands: // :v/ *public/d // :%s/.\+\(\<[^(]\+\)(.*/\1/g // :%s/.*/"&",/ - private static final String[] UDJC_FUNCTIONS = { - "addResultFile", - "addRowListener", - "addStepListener", - "checkFeedback", - "cleanup", - "decrementLinesRead", - "decrementLinesWritten", - "dispose", - "findInputRowSet", - "findInputRowSet", - "findOutputRowSet", - "findOutputRowSet", - "getClusterSize", - "getCopy", - "getErrorRowMeta", - "getErrors", - "getFields", - "getInfoSteps", - "getInputRowMeta", - "getInputRowSets", - "getLinesInput", - "getLinesOutput", - "getLinesRead", - "getLinesRejected", - "getLinesSkipped", - "getLinesUpdated", - "getLinesWritten", - "getOutputRowSets", - "getPartitionID", - "getPartitionTargets", - "getProcessed", - "getRepartitioning", - "getResultFiles", - "getRow", - "getRowFrom", - "getRowListeners", - "getRuntime", - "getSlaveNr", - "getSocketRepository", - "getStatus", - "getStatusDescription", - "getStepDataInterface", - "getStepID", - "getStepListeners", - "getStepMeta", - "getStepname", - "getTrans", - "getTransMeta", - "getTypeId", - "getUniqueStepCountAcrossSlaves", - "getUniqueStepNrAcrossSlaves", - "getVariable", - "incrementLinesInput", - "incrementLinesOutput", - "incrementLinesRead", - "incrementLinesRejected", - "incrementLinesSkipped", - "incrementLinesUpdated", - "incrementLinesWritten", - "init", - "initBeforeStart", - "isDistributed", - "isInitialising", - "isPartitioned", - "isSafeModeEnabled", - "isStopped", - "isUsingThreadPriorityManagment", - "logBasic", - "logDebug", - "logDetailed", - "logError", - "logError", - "logMinimal", - "logRowlevel", - "logSummary", - "markStart", - "markStop", - "openRemoteInputStepSocketsOnce", - "openRemoteOutputStepSocketsOnce", - "outputIsDone", - "processRow", - "putError", - "putRow", - "putRowTo", - "removeRowListener", - "rowsetInputSize", - "rowsetOutputSize", - "safeModeChecking", - "setErrors", - "setInputRowMeta", - "setInputRowSets", - "setLinesInput", - "setLinesOutput", - "setLinesRead", - "setLinesRejected", - "setLinesSkipped", - "setLinesUpdated", - "setLinesWritten", - "setOutputDone", - "setOutputRowSets", - "setStepListeners", - "setVariable", - "stopAll", - "stopRunning", - "toString", - }; + private static final List UDJC_FUNCTIONS = + List.of( + "addResultFile", + "addRowListener", + "addStepListener", + "checkFeedback", + "cleanup", + "decrementLinesRead", + "decrementLinesWritten", + "dispose", + "findInputRowSet", + "findInputRowSet", + "findOutputRowSet", + "findOutputRowSet", + "getClusterSize", + "getCopy", + "getErrorRowMeta", + "getErrors", + "getFields", + "getInfoSteps", + "getInputRowMeta", + "getInputRowSets", + "getLinesInput", + "getLinesOutput", + "getLinesRead", + "getLinesRejected", + "getLinesSkipped", + "getLinesUpdated", + "getLinesWritten", + "getOutputRowSets", + "getPartitionID", + "getPartitionTargets", + "getProcessed", + "getRepartitioning", + "getResultFiles", + "getRow", + "getRowFrom", + "getRowListeners", + "getRuntime", + "getSlaveNr", + "getSocketRepository", + "getStatus", + "getStatusDescription", + "getStepDataInterface", + "getStepID", + "getStepListeners", + "getStepMeta", + "getStepname", + "getTrans", + "getTransMeta", + "getTypeId", + "getUniqueStepCountAcrossSlaves", + "getUniqueStepNrAcrossSlaves", + "getVariable", + "incrementLinesInput", + "incrementLinesOutput", + "incrementLinesRead", + "incrementLinesRejected", + "incrementLinesSkipped", + "incrementLinesUpdated", + "incrementLinesWritten", + "init", + "initBeforeStart", + "isDistributed", + "isInitialising", + "isPartitioned", + "isSafeModeEnabled", + "isStopped", + "isUsingThreadPriorityManagment", + "logBasic", + "logDebug", + "logDetailed", + "logError", + "logError", + "logMinimal", + "logRowlevel", + "logSummary", + "markStart", + "markStop", + "openRemoteInputStepSocketsOnce", + "openRemoteOutputStepSocketsOnce", + "outputIsDone", + "processRow", + "putError", + "putRow", + "putRowTo", + "removeRowListener", + "rowsetInputSize", + "rowsetOutputSize", + "safeModeChecking", + "setErrors", + "setInputRowMeta", + "setInputRowSets", + "setLinesInput", + "setLinesOutput", + "setLinesRead", + "setLinesRejected", + "setLinesSkipped", + "setLinesUpdated", + "setLinesWritten", + "setOutputDone", + "setOutputRowSets", + "setStepListeners", + "setVariable", + "stopAll", + "stopRunning", + "toString"); } diff --git a/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/JavaScriptHighlight.java b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/JavaScriptHighlight.java index 0252ca3a6d..89193ec260 100644 --- a/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/JavaScriptHighlight.java +++ b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/JavaScriptHighlight.java @@ -19,23 +19,24 @@ import java.io.IOException; import java.io.StringReader; -import java.util.Hashtable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.Vector; +import org.apache.hop.core.util.Utils; +import org.apache.hop.ui.core.PropsUi; import org.apache.hop.ui.core.gui.GuiResource; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.LineStyleEvent; import org.eclipse.swt.custom.LineStyleListener; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; -import org.eclipse.swt.graphics.Color; public class JavaScriptHighlight implements LineStyleListener { - JavaScanner scanner = new JavaScanner(); - int[] tokenColors; - Color[] colors; - Vector blockComments = new Vector<>(); + JavaScanner scanner; + StyleAttribute[] styleAttributes; + ArrayList blockComments = new ArrayList<>(); public static final int EOF = -1; public static final int EOL = 10; @@ -44,35 +45,33 @@ public class JavaScriptHighlight implements LineStyleListener { public static final int WHITE = 1; public static final int KEY = 2; public static final int COMMENT = 3; // single line comment: // + public static final int SYMBOL = 4; public static final int STRING = 5; public static final int OTHER = 6; public static final int NUMBER = 7; - public static final int FUNCTIONS = 8; + public static final int FUNCTION = 8; public static final int MAXIMUM_TOKEN = 9; public JavaScriptHighlight() { - initializeColors(); - scanner = new JavaScanner(); + this(List.of()); } - public JavaScriptHighlight(String[] strArrETLFunctions) { - initializeColors(); - scanner = new JavaScanner(); - scanner.setETLKeywords(strArrETLFunctions); - scanner.initializeETLFunctions(); + public JavaScriptHighlight(List functionNames) { + initializeStyles(); + scanner = new JavaScanner(functionNames); } - Color getColor(int type) { - if (type < 0 || type >= tokenColors.length) { + StyleAttribute getStyleAttribute(int type) { + if (type < 0 || type >= styleAttributes.length) { return null; } - return colors[tokenColors[type]]; + return styleAttributes[type]; } boolean inBlockComment(int start, int end) { for (int i = 0; i < blockComments.size(); i++) { - int[] offsets = blockComments.elementAt(i); + int[] offsets = blockComments.get(i); // start of comment in the line if ((offsets[0] >= start) && (offsets[0] <= end)) { return true; @@ -88,30 +87,24 @@ boolean inBlockComment(int start, int end) { return false; } - void initializeColors() { - final GuiResource guiResource = GuiResource.getInstance(); - colors = - new Color[] { - guiResource.getColorBlack(), - guiResource.getColorRed(), - guiResource.getColorDarkGreen(), - guiResource.getColorBlue(), - guiResource.getColorOrange() - }; - tokenColors = new int[MAXIMUM_TOKEN]; - tokenColors[WORD] = 0; - tokenColors[WHITE] = 0; - tokenColors[KEY] = 3; - tokenColors[COMMENT] = 1; - tokenColors[STRING] = 2; - tokenColors[OTHER] = 0; - tokenColors[NUMBER] = 0; - tokenColors[FUNCTIONS] = 4; - } - - void disposeColors() { - for (int i = 0; i < colors.length; i++) { - colors[i].dispose(); + void initializeStyles() { + GuiResource resource = GuiResource.getInstance(); + styleAttributes = new StyleAttribute[MAXIMUM_TOKEN]; + styleAttributes[WORD] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[WHITE] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[STRING] = new StyleAttribute(resource.getColorDarkGreen(), SWT.NORMAL); + styleAttributes[OTHER] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[NUMBER] = new StyleAttribute(resource.getColorOrange(), SWT.NORMAL); + if (PropsUi.getInstance().isDarkMode()) { + styleAttributes[COMMENT] = new StyleAttribute(resource.getColorGray(), SWT.ITALIC); + styleAttributes[KEY] = new StyleAttribute(resource.getColor(30, 144, 255), SWT.NORMAL); + styleAttributes[SYMBOL] = new StyleAttribute(resource.getColor(243, 126, 131), SWT.NORMAL); + styleAttributes[FUNCTION] = new StyleAttribute(resource.getColor(177, 102, 218), SWT.NORMAL); + } else { + styleAttributes[COMMENT] = new StyleAttribute(resource.getColorDarkGray(), SWT.ITALIC); + styleAttributes[KEY] = new StyleAttribute(resource.getColorBlue(), SWT.NORMAL); + styleAttributes[SYMBOL] = new StyleAttribute(resource.getColorDarkRed(), SWT.NORMAL); + styleAttributes[FUNCTION] = new StyleAttribute(resource.getColor(148, 0, 211), SWT.NORMAL); } } @@ -121,15 +114,20 @@ void disposeColors() { * background color (output) */ public void lineGetStyle(LineStyleEvent event) { - Vector styles = new Vector<>(); - int token; + ArrayList styles = new ArrayList<>(); StyleRange lastStyle; if (inBlockComment(event.lineOffset, event.lineOffset + event.lineText.length())) { - styles.addElement( - new StyleRange(event.lineOffset, event.lineText.length() + 4, colors[2], null)); - event.styles = new StyleRange[styles.size()]; - styles.copyInto(event.styles); + StyleAttribute attribute = getStyleAttribute(COMMENT); + + styles.add( + new StyleRange( + event.lineOffset, + event.lineText.length() + 4, + attribute.getForeground(), + null, + attribute.getStyle())); + event.styles = styles.toArray(new StyleRange[styles.size()]); return; } scanner.setRange(event.lineText); @@ -137,12 +135,12 @@ public void lineGetStyle(LineStyleEvent event) { if (xs != null) { parseBlockComments(xs); } - token = scanner.nextToken(); + int token = scanner.nextToken(); while (token != EOF) { if (token != OTHER) { if ((token == WHITE) && (!styles.isEmpty())) { int start = scanner.getStartOffset() + event.lineOffset; - lastStyle = styles.lastElement(); + lastStyle = styles.get(styles.size() - 1); if (lastStyle.fontStyle != SWT.NORMAL) { if (lastStyle.start + lastStyle.length == start) { // have the white space take on the style before it to minimize font style @@ -151,23 +149,27 @@ public void lineGetStyle(LineStyleEvent event) { } } } else { - Color color = getColor(token); - if (color != colors[0]) { // hardcoded default foreground color, black + StyleAttribute attribute = getStyleAttribute(token); + if (attribute != styleAttributes[0]) { // hardcoded default foreground color, black StyleRange style = new StyleRange( - scanner.getStartOffset() + event.lineOffset, scanner.getLength(), color, null); + scanner.getStartOffset() + event.lineOffset, + scanner.getLength(), + attribute.getForeground(), + null, + attribute.getStyle()); if (token == KEY) { style.fontStyle = SWT.BOLD; } if (styles.isEmpty()) { - styles.addElement(style); + styles.add(style); } else { - lastStyle = styles.lastElement(); + lastStyle = styles.get(styles.size() - 1); if (lastStyle.similarTo(style) && (lastStyle.start + lastStyle.length == style.start)) { lastStyle.length += style.length; } else { - styles.addElement(style); + styles.add(style); } } } @@ -175,12 +177,11 @@ public void lineGetStyle(LineStyleEvent event) { } token = scanner.nextToken(); } - event.styles = new StyleRange[styles.size()]; - styles.copyInto(event.styles); + event.styles = styles.toArray(new StyleRange[styles.size()]); } public void parseBlockComments(String text) { - blockComments = new Vector<>(); + blockComments = new ArrayList<>(); StringReader buffer = new StringReader(text); int ch; boolean blkComment = false; @@ -195,7 +196,7 @@ public void parseBlockComments(String text) { { if (blkComment) { offsets[1] = cnt; - blockComments.addElement(offsets); + blockComments.add(offsets); } done = true; break; @@ -222,7 +223,7 @@ public void parseBlockComments(String text) { if (ch == '/') { blkComment = false; offsets[1] = cnt; - blockComments.addElement(offsets); + blockComments.add(offsets); } } cnt++; @@ -240,13 +241,10 @@ public void parseBlockComments(String text) { } } - /** A simple fuzzy scanner for Java */ + /** A simple fuzzy scanner for JavaScript */ public class JavaScanner { - protected Map fgKeys = null; - protected Map fgFunctions = null; - protected Map kfKeys = null; - protected Map kfFunctions = null; + protected Map reserved = new HashMap<>(); protected StringBuilder fBuffer = new StringBuilder(); protected String fDoc; protected int fPos; @@ -254,83 +252,74 @@ public class JavaScanner { protected int fStartToken; protected boolean fEofSeen = false; - private String[] kfKeywords = {"num2str"}; - - private String[] fgKeywords = { - "array", - "break", - "case", - "catch", - "const", - "continue", - "Date", - "default", - "delete", - "do", - "else", - "eval", - "escape", - "false", - "finally", - "float", - "for", - "function", - "if", - "in", - "instanceof", - "isFinite", - "isNaN", - "new", - "Number", - "null", - "String", - "switch", - "this", - "then", - "throw", - "to", - "true", - "try", - "typeof", - "parseInt", - "parseFloat", - "return", - "unescape", - "var", - "void", - "with", - "while" - }; - - public JavaScanner() { - initialize(); - initializeETLFunctions(); + private static final List KEYWORDS = + List.of( + "array", + "break", + "case", + "catch", + "const", + "continue", + "Date", + "default", + "delete", + "do", + "else", + "eval", + "escape", + "false", + "finally", + "float", + "for", + "function", + "if", + "in", + "instanceof", + "isFinite", + "isNaN", + "new", + "Number", + "null", + "String", + "switch", + "this", + "then", + "throw", + "to", + "true", + "try", + "typeof", + "parseInt", + "parseFloat", + "return", + "unescape", + "var", + "void", + "with", + "while"); + + public JavaScanner(List functionNames) { + addKeywords(KEYWORDS); + addFunctionNames(functionNames); } - /** Returns the ending location of the current token in the document. */ - public final int getLength() { - return fPos - fStartToken; - } - - /** Initialize the lookup table. */ - void initialize() { - fgKeys = new Hashtable<>(); - Integer k = Integer.valueOf(KEY); - for (int i = 0; i < fgKeywords.length; i++) { - fgKeys.put(fgKeywords[i], k); + public void addKeywords(List reservedKeywords) { + if (Utils.isEmpty(reservedKeywords)) { + return; } + reservedKeywords.forEach(name -> reserved.put(name, Integer.valueOf(KEY))); } - public void setETLKeywords(String[] kfKeywords) { - this.kfKeywords = kfKeywords; + public void addFunctionNames(List functionNames) { + if (Utils.isEmpty(functionNames)) { + return; + } + functionNames.forEach(name -> reserved.put(name, Integer.valueOf(FUNCTION))); } - void initializeETLFunctions() { - kfKeys = new Hashtable<>(); - Integer k = Integer.valueOf(FUNCTIONS); - for (int i = 0; i < kfKeywords.length; i++) { - kfKeys.put(kfKeywords[i], k); - } + /** Returns the ending location of the current token in the document. */ + public final int getLength() { + return fPos - fStartToken; } /** Returns the starting location of the current token in the document. */ @@ -356,10 +345,8 @@ public int nextToken() { return COMMENT; } } - } else { - unread(c); } - return OTHER; + return SYMBOL; case '\'': // char const for (; ; ) { c = read(); @@ -394,6 +381,28 @@ public int nextToken() { } } + case '(', + ')', + '{', + '}', + '[', + ']', + '*', + '+', + '-', + '=', + '>', + '<', + '!', + ':', + '.', + ',', + ';', + '&', + '|', + '^': + return SYMBOL; + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': do { c = read(); @@ -415,13 +424,9 @@ public int nextToken() { c = read(); } while (Character.isJavaIdentifierPart((char) c)); unread(c); - Integer i = fgKeys.get(fBuffer.toString()); - if (i != null) { - return i.intValue(); - } - i = kfKeys.get(fBuffer.toString()); - if (i != null) { - return i.intValue(); + Integer token = reserved.get(fBuffer.toString()); + if (token != null) { + return token.intValue(); } return WORD; } diff --git a/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/SQLValuesHighlight.java b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/SQLValuesHighlight.java deleted file mode 100644 index 581be8fc07..0000000000 --- a/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/SQLValuesHighlight.java +++ /dev/null @@ -1,847 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hop.ui.core.widget.highlight; - -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.Vector; -import org.apache.hop.core.database.SqlScriptStatement; -import org.apache.hop.core.util.Utils; -import org.apache.hop.ui.core.gui.GuiResource; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.LineStyleEvent; -import org.eclipse.swt.custom.LineStyleListener; -import org.eclipse.swt.custom.StyleRange; -import org.eclipse.swt.custom.StyledText; -import org.eclipse.swt.graphics.Color; - -public class SQLValuesHighlight implements LineStyleListener { - JavaScanner scanner = new JavaScanner(); - int[] tokenColors; - Color[] colors; - Vector blockComments = new Vector<>(); - - public static final int EOF = -1; - public static final int EOL = 10; - - public static final int WORD = 0; - public static final int WHITE = 1; - public static final int KEY = 2; - public static final int COMMENT = 3; // single line comment: // - public static final int STRING = 5; - public static final int OTHER = 6; - public static final int NUMBER = 7; - public static final int FUNCTIONS = 8; - - public static final int MAXIMUM_TOKEN = 9; - - private List scriptStatements; - - public SQLValuesHighlight() { - initializeColors(); - scriptStatements = new ArrayList<>(); - scanner = new JavaScanner(); - } - - public SQLValuesHighlight(List sqlKeywords) { - String[] strArrSQLFunctions = new String[sqlKeywords.size()]; - strArrSQLFunctions = sqlKeywords.toArray(strArrSQLFunctions); - initializeColors(); - scriptStatements = new ArrayList<>(); - scanner = new JavaScanner(); - scanner.setSQLKeywords(strArrSQLFunctions); - scanner.initializeSQLFunctions(); - } - - Color getColor(int type) { - if (type < 0 || type >= tokenColors.length) { - return null; - } - return colors[tokenColors[type]]; - } - - boolean inBlockComment(int start, int end) { - for (int i = 0; i < blockComments.size(); i++) { - int[] offsets = blockComments.elementAt(i); - // start of comment in the line - if ((offsets[0] >= start) && (offsets[0] <= end)) { - return true; - } - // end of comment in the line - if ((offsets[1] >= start) && (offsets[1] <= end)) { - return true; - } - if ((offsets[0] <= start) && (offsets[1] >= end)) { - return true; - } - } - return false; - } - - void initializeColors() { - colors = - new Color[] { - GuiResource.getInstance().getColorBlack(), // black - GuiResource.getInstance().getColorRed(), // red - GuiResource.getInstance().getColorDarkGreen(), // green - GuiResource.getInstance().getColorBlue(), // blue - GuiResource.getInstance().getColorMagenta() // SQL Functions / Rose - }; - tokenColors = new int[MAXIMUM_TOKEN]; - tokenColors[WORD] = 0; - tokenColors[WHITE] = 0; - tokenColors[KEY] = 3; - tokenColors[COMMENT] = 2; - tokenColors[STRING] = 1; - tokenColors[OTHER] = 0; - tokenColors[NUMBER] = 0; - tokenColors[FUNCTIONS] = 4; - } - - /** - * Event.detail line start offset (input) Event.text line text (input) LineStyleEvent.styles - * Enumeration of StyleRanges, need to be in order. (output) LineStyleEvent.background line - * background color (output) - */ - public void lineGetStyle(LineStyleEvent event) { - Vector styles = new Vector<>(); - int token; - StyleRange lastStyle; - - if (inBlockComment(event.lineOffset, event.lineOffset + event.lineText.length())) { - styles.addElement( - new StyleRange(event.lineOffset, event.lineText.length() + 4, colors[1], null)); - event.styles = new StyleRange[styles.size()]; - styles.copyInto(event.styles); - return; - } - scanner.setRange(event.lineText); - String xs = ((StyledText) event.widget).getText(); - if (xs != null) { - parseBlockComments(xs); - } - token = scanner.nextToken(); - while (token != EOF) { - if (token != OTHER) { - if ((token == WHITE) && (!styles.isEmpty())) { - int start = scanner.getStartOffset() + event.lineOffset; - lastStyle = styles.lastElement(); - if (lastStyle.fontStyle != SWT.NORMAL) { - if (lastStyle.start + lastStyle.length == start) { - // have the white space take on the style before it to minimize font style - // changes - lastStyle.length += scanner.getLength(); - } - } - } else { - Color color = getColor(token); - if (color != colors[0]) { // hardcoded default foreground color, black - StyleRange style = - new StyleRange( - scanner.getStartOffset() + event.lineOffset, scanner.getLength(), color, null); - if (styles.isEmpty()) { - styles.addElement(style); - } else { - lastStyle = styles.lastElement(); - if (lastStyle.similarTo(style) - && (lastStyle.start + lastStyle.length == style.start)) { - lastStyle.length += style.length; - } else { - styles.addElement(style); - } - } - } - } - } - token = scanner.nextToken(); - } - - // See which backgrounds to color... - // - if (scriptStatements != null) { - for (SqlScriptStatement statement : scriptStatements) { - // Leave non-executed statements alone. - // - StyleRange styleRange = new StyleRange(); - styleRange.start = statement.getFromIndex(); - styleRange.length = statement.getToIndex() - statement.getFromIndex(); - - if (statement.isComplete()) { - if (statement.isOk()) { - // GuiResource.getInstance().getColor(63, 127, 95), // green - - styleRange.background = GuiResource.getInstance().getColor(244, 238, 224); // honey dew - } else { - styleRange.background = - GuiResource.getInstance().getColor(250, 235, 215); // Antique White - } - } else { - styleRange.background = GuiResource.getInstance().getColorWhite(); - } - - styles.add(styleRange); - } - } - - event.styles = new StyleRange[styles.size()]; - styles.copyInto(event.styles); - } - - public void parseBlockComments(String text) { - blockComments = new Vector<>(); - StringReader buffer = new StringReader(text); - int ch; - boolean blkComment = false; - int cnt = 0; - int[] offsets = new int[2]; - boolean done = false; - - try { - while (!done) { - switch (ch = buffer.read()) { - case -1: - { - if (blkComment) { - offsets[1] = cnt; - blockComments.addElement(offsets); - } - done = true; - break; - } - case '/': - { - ch = buffer.read(); - if ((ch == '*') && (!blkComment)) { - offsets = new int[2]; - offsets[0] = cnt; - blkComment = true; - cnt++; - } else { - cnt++; - } - cnt++; - break; - } - case '*': - { - if (blkComment) { - ch = buffer.read(); - cnt++; - if (ch == '/') { - blkComment = false; - offsets[1] = cnt; - blockComments.addElement(offsets); - } - } - cnt++; - break; - } - default: - { - cnt++; - break; - } - } - } - } catch (IOException e) { - // ignore errors - } - } - - /** A simple fuzzy scanner for Java */ - public class JavaScanner { - protected Map fgKeys = null; - protected Map fgFunctions = null; - protected Map kfKeys = null; - protected Map kfFunctions = null; - - protected StringBuilder fBuffer = new StringBuilder(); - protected String fDoc; - protected int fPos; - protected int fEnd; - protected int fStartToken; - protected boolean fEofSeen = false; - - private String[] kfKeywords = { - "getdate", - "case", - "convert", - "left", - "right", - "isnumeric", - "isdate", - "isnumber", - "number", - "finally", - "cast", - "var", - "fetch_status", - "isnull", - "charindex", - "difference", - "len", - "nchar", - "quotename", - "replicate", - "reverse", - "str", - "stuff", - "unicode", - "ascii", - "char", - "to_char", - "to_date", - "to_number", - "nvl", - "sysdate", - "corr", - "count", - "grouping", - "max", - "min", - "stdev", - "sum", - "concat", - "length", - "locate", - "ltrim", - "posstr", - "repeat", - "replace", - "rtrim", - "soundex", - "space", - "substr", - "substring", - "trunc", - "nextval", - "currval", - "getclobval", - "char_length", - "compare", - "patindex", - "sortkey", - "uscalar", - "current_date", - "current_time", - "current_timestamp", - "current_user", - "session_user", - "system_user", - "curdate", - "curtime", - "database", - "now", - "sysdate", - "today", - "user", - "version", - "coalesce", - "nullif", - "octet_length", - "datalength", - "decode", - "greatest", - "ifnull", - "least", - "||", - "char_length", - "character_length", - "collate", - "concatenate", - "like", - "lower", - "position", - "translate", - "upper", - "char_octet_length", - "character_maximum_length", - "character_octet_length", - "ilike", - "initcap", - "instr", - "lcase", - "lpad", - "patindex", - "rpad", - "ucase", - "bit_length", - "&", - "|", - "^", - "%", - "+", - "-", - "*", - "/", - "(", - ")", - "abs", - "asin", - "atan", - "ceiling", - "cos", - "cot", - "exp", - "floor", - "ln", - "log", - "log10", - "mod", - "pi", - "power", - "rand", - "round", - "sign", - "sin", - "sqrt", - "tan", - "trunc", - "extract", - "interval", - "overlaps", - "adddate", - "age", - "date_add", - "dateformat", - "date_part", - "date_sub", - "datediff", - "dateadd", - "datename", - "datepart", - "day", - "dayname", - "dayofmonth", - "dayofweek", - "dayofyear", - "hour", - "last_day", - "minute", - "month", - "month_between", - "monthname", - "next_day", - "second", - "sub_date", - "week", - "year", - "dbo", - "log", - "objectproperty" - }; - - private String[] fgKeywords = { - "create", - "procedure", - "as", - "set", - "nocount", - "on", - "declare", - "varchar", - "print", - "table", - "int", - "tintytext", - "select", - "from", - "where", - "and", - "or", - "insert", - "into", - "cursor", - "read_only", - "for", - "open", - "fetch", - "next", - "end", - "deallocate", - "table", - "drop", - "exec", - "begin", - "close", - "update", - "delete", - "truncate", - "inner", - "outer", - "join", - "union", - "all", - "float", - "when", - "nolock", - "with", - "false", - "datetime", - "dare", - "time", - "hour", - "array", - "minute", - "second", - "millisecond", - "view", - "function", - "catch", - "const", - "continue", - "compute", - "browse", - "option", - "date", - "default", - "do", - "raw", - "auto", - "explicit", - "xmldata", - "elements", - "binary", - "base64", - "read", - "outfile", - "asc", - "desc", - "else", - "eval", - "escape", - "having", - "limit", - "offset", - "of", - "intersect", - "except", - "using", - "variance", - "specific", - "language", - "body", - "returns", - "specific", - "deterministic", - "not", - "external", - "action", - "reads", - "static", - "inherit", - "called", - "order", - "group", - "by", - "natural", - "full", - "exists", - "between", - "some", - "any", - "unique", - "match", - "value", - "limite", - "minus", - "references", - "grant", - "on", - "top", - "index", - "bigint", - "text", - "char", - "use", - "move", - "exec", - "init", - "name", - "noskip", - "skip", - "noformat", - "format", - "stats", - "disk", - "from", - "to", - "rownum", - "alter", - "add", - "remove", - "move", - "alter", - "add", - "remove", - "lineno", - "modify", - "if", - "else", - "in", - "is", - "new", - "Number", - "null", - "string", - "switch", - "this", - "then", - "throw", - "true", - "false", - "try", - "return", - "with", - "while", - "start", - "connect", - "optimize", - "first", - "only", - "rows", - "sequence", - "blob", - "clob", - "image", - "binary", - "column", - "decimal", - "distinct", - "primary", - "key", - "timestamp", - "varbinary", - "nvarchar", - "nchar", - "longnvarchar", - "nclob", - "numeric", - "constraint", - "dbcc", - "backup", - "bit", - "clustered", - "pad_index", - "off", - "statistics_norecompute", - "ignore_dup_key", - "allow_row_locks", - "allow_page_locks", - "textimage_on", - "double", - "rollback", - "tran", - "transaction", - "commit" - }; - - public JavaScanner() { - initialize(); - initializeSQLFunctions(); - } - - /** Returns the ending location of the current token in the document. */ - public final int getLength() { - return fPos - fStartToken; - } - - /** Initialize the lookup table. */ - void initialize() { - fgKeys = new Hashtable<>(); - Integer k = Integer.valueOf(KEY); - for (int i = 0; i < fgKeywords.length; i++) { - fgKeys.put(fgKeywords[i], k); - } - } - - public void setSQLKeywords(String[] kfKeywords) { - this.kfKeywords = kfKeywords; - } - - public String[] getSQLKeywords() { - return kfKeywords; - } - - public void initializeSQLFunctions() { - kfKeys = new Hashtable<>(); - Integer k = Integer.valueOf(FUNCTIONS); - for (int i = 0; i < kfKeywords.length; i++) { - kfKeys.put(kfKeywords[i], k); - } - } - - /** Returns the starting location of the current token in the document. */ - public final int getStartOffset() { - return fStartToken; - } - - /** Returns the next lexical token in the document. */ - public int nextToken() { - int c; - fStartToken = fPos; - while (true) { - switch (c = read()) { - case EOF: - return EOF; - case '/': // comment - c = read(); - if (c == '/') { - while (true) { - c = read(); - if ((c == EOF) || (c == EOL)) { - unread(c); - return COMMENT; - } - } - } else { - unread(c); - } - return OTHER; - case '-': // comment - c = read(); - if (c == '-') { - while (true) { - c = read(); - if ((c == EOF) || (c == EOL)) { - unread(c); - return COMMENT; - } - } - } else { - unread(c); - } - return OTHER; - case '\'': // char const - for (; ; ) { - c = read(); - switch (c) { - case '\'': - return STRING; - case EOF: - unread(c); - return STRING; - case '\\': - c = read(); - break; - default: - break; - } - } - - case '"': // string - for (; ; ) { - c = read(); - switch (c) { - case '"': - return STRING; - case EOF: - unread(c); - return STRING; - case '\\': - c = read(); - break; - default: - break; - } - } - - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - do { - c = read(); - } while (Character.isDigit((char) c)); - unread(c); - return NUMBER; - default: - if (Character.isWhitespace((char) c)) { - do { - c = read(); - } while (Character.isWhitespace((char) c)); - unread(c); - return WHITE; - } - if (Character.isJavaIdentifierStart((char) c)) { - fBuffer.setLength(0); - do { - fBuffer.append((char) c); - c = read(); - } while (Character.isJavaIdentifierPart((char) c)); - unread(c); - Integer i = fgKeys.get(fBuffer.toString()); - if (i != null) { - return i.intValue(); - } - i = kfKeys.get(fBuffer.toString()); - if (i != null) { - return i.intValue(); - } - return WORD; - } - return OTHER; - } - } - } - - /** Returns next character. */ - protected int read() { - if (fPos <= fEnd) { - return fDoc.charAt(fPos++); - } - return EOF; - } - - public void setRange(String text) { - fDoc = text.toLowerCase(); - fPos = 0; - fEnd = fDoc.length() - 1; - } - - protected void unread(int c) { - if (c != EOF) { - fPos--; - } - } - } - - /** - * @return the scriptStatements - */ - public List getScriptStatements() { - return scriptStatements; - } - - /** - * @param scriptStatements the scriptStatements to set - */ - public void setScriptStatements(List scriptStatements) { - this.scriptStatements = scriptStatements; - } - - public void addKeyWords(String[] reservedWords) { - if (Utils.isEmpty(reservedWords)) { - return; - } - - scanner.setSQLKeywords(reservedWords); - scanner.initializeSQLFunctions(); - } -} diff --git a/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/SqlHighlight.java b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/SqlHighlight.java new file mode 100644 index 0000000000..a8251f4192 --- /dev/null +++ b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/SqlHighlight.java @@ -0,0 +1,833 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hop.ui.core.widget.highlight; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.hop.core.database.SqlScriptStatement; +import org.apache.hop.core.util.Utils; +import org.apache.hop.ui.core.PropsUi; +import org.apache.hop.ui.core.gui.GuiResource; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.LineStyleEvent; +import org.eclipse.swt.custom.LineStyleListener; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.custom.StyledText; + +public class SqlHighlight implements LineStyleListener { + SqlScanner scanner; + StyleAttribute[] styleAttributes; + ArrayList blockComments = new ArrayList<>(); + + public static final int EOF = -1; + public static final int EOL = 10; + + public static final int WORD = 0; + public static final int WHITE = 1; + public static final int KEY = 2; + public static final int COMMENT = 3; // single line comment: // + public static final int SYMBOL = 4; + public static final int STRING = 5; + public static final int OTHER = 6; + public static final int NUMBER = 7; + public static final int FUNCTION = 8; + public static final int PARAM = 9; + + public static final int MAXIMUM_TOKEN = 10; + + private List scriptStatements; + + public SqlHighlight() { + this(List.of()); + } + + public SqlHighlight(List functionNames) { + initializeStyles(); + scriptStatements = new ArrayList<>(); + scanner = new SqlScanner(functionNames); + } + + StyleAttribute getStyleAttribute(int type) { + if (type < 0 || type >= styleAttributes.length) { + return null; + } + return styleAttributes[type]; + } + + boolean inBlockComment(int start, int end) { + for (int i = 0; i < blockComments.size(); i++) { + int[] offsets = blockComments.get(i); + // start of comment in the line + if ((offsets[0] >= start) && (offsets[0] <= end)) { + return true; + } + // end of comment in the line + if ((offsets[1] >= start) && (offsets[1] <= end)) { + return true; + } + if ((offsets[0] <= start) && (offsets[1] >= end)) { + return true; + } + } + return false; + } + + void initializeStyles() { + GuiResource resource = GuiResource.getInstance(); + styleAttributes = new StyleAttribute[MAXIMUM_TOKEN]; + styleAttributes[WORD] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[WHITE] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[STRING] = new StyleAttribute(resource.getColorDarkGreen(), SWT.NORMAL); + styleAttributes[OTHER] = new StyleAttribute(resource.getColorBlack(), SWT.NORMAL); + styleAttributes[NUMBER] = new StyleAttribute(resource.getColorOrange(), SWT.NORMAL); + styleAttributes[PARAM] = new StyleAttribute(resource.getColor(148, 0, 211), SWT.BOLD); + if (PropsUi.getInstance().isDarkMode()) { + styleAttributes[COMMENT] = new StyleAttribute(resource.getColorGray(), SWT.ITALIC); + styleAttributes[KEY] = new StyleAttribute(resource.getColor(30, 144, 255), SWT.NORMAL); + styleAttributes[SYMBOL] = new StyleAttribute(resource.getColor(243, 126, 131), SWT.NORMAL); + styleAttributes[FUNCTION] = new StyleAttribute(resource.getColor(177, 102, 218), SWT.NORMAL); + } else { + styleAttributes[COMMENT] = new StyleAttribute(resource.getColorDarkGray(), SWT.ITALIC); + styleAttributes[KEY] = new StyleAttribute(resource.getColorBlue(), SWT.NORMAL); + styleAttributes[SYMBOL] = new StyleAttribute(resource.getColorDarkRed(), SWT.NORMAL); + styleAttributes[FUNCTION] = new StyleAttribute(resource.getColor(148, 0, 211), SWT.NORMAL); + } + } + + /** + * Event.detail line start offset (input) Event.text line text (input) LineStyleEvent.styles + * Enumeration of StyleRanges, need to be in order. (output) LineStyleEvent.background line + * background color (output) + */ + public void lineGetStyle(LineStyleEvent event) { + ArrayList styles = new ArrayList<>(); + StyleRange lastStyle; + + if (inBlockComment(event.lineOffset, event.lineOffset + event.lineText.length())) { + StyleAttribute attribute = getStyleAttribute(COMMENT); + styles.add( + new StyleRange( + event.lineOffset, + event.lineText.length() + 4, + attribute.getForeground(), + null, + attribute.getStyle())); + event.styles = styles.toArray(new StyleRange[styles.size()]); + return; + } + scanner.setRange(event.lineText); + String xs = ((StyledText) event.widget).getText(); + if (xs != null) { + parseBlockComments(xs); + } + int token = scanner.nextToken(); + while (token != EOF) { + if (token != OTHER) { + if ((token == WHITE) && (!styles.isEmpty())) { + int start = scanner.getStartOffset() + event.lineOffset; + lastStyle = styles.get(styles.size() - 1); + if (lastStyle.fontStyle != SWT.NORMAL) { + if (lastStyle.start + lastStyle.length == start) { + // have the white space take on the style before it to minimize font style + // changes + lastStyle.length += scanner.getLength(); + } + } + } else { + StyleAttribute attribute = getStyleAttribute(token); + if (attribute != styleAttributes[0]) { // hardcoded default foreground color, black + StyleRange styleRange = + new StyleRange( + scanner.getStartOffset() + event.lineOffset, + scanner.getLength(), + attribute.getForeground(), + null, + attribute.getStyle()); + if (styles.isEmpty()) { + styles.add(styleRange); + } else { + lastStyle = styles.get(styles.size() - 1); + if (lastStyle.similarTo(styleRange) + && (lastStyle.start + lastStyle.length == styleRange.start)) { + lastStyle.length += styleRange.length; + } else { + styles.add(styleRange); + } + } + } + } + } + token = scanner.nextToken(); + } + + // See which backgrounds to color... + // + if (scriptStatements != null) { + for (SqlScriptStatement statement : scriptStatements) { + // Leave non-executed statements alone. + // + StyleRange styleRange = new StyleRange(); + styleRange.start = statement.getFromIndex(); + styleRange.length = statement.getToIndex() - statement.getFromIndex(); + + if (statement.isComplete()) { + if (statement.isOk()) { + // GuiResource.getInstance().getColor(63, 127, 95), // green + + styleRange.background = GuiResource.getInstance().getColor(244, 238, 224); // honey dew + } else { + styleRange.background = + GuiResource.getInstance().getColor(250, 235, 215); // Antique White + } + } else { + styleRange.background = GuiResource.getInstance().getColorWhite(); + } + + styles.add(styleRange); + } + } + + event.styles = styles.toArray(new StyleRange[styles.size()]); + } + + public void parseBlockComments(String text) { + blockComments = new ArrayList<>(); + StringReader buffer = new StringReader(text); + int ch; + boolean blkComment = false; + int cnt = 0; + int[] offsets = new int[2]; + boolean done = false; + + try { + while (!done) { + switch (ch = buffer.read()) { + case -1: + { + if (blkComment) { + offsets[1] = cnt; + blockComments.add(offsets); + } + done = true; + break; + } + case '/': + { + ch = buffer.read(); + if ((ch == '*') && (!blkComment)) { + offsets = new int[2]; + offsets[0] = cnt; + blkComment = true; + cnt++; + } else { + cnt++; + } + cnt++; + break; + } + case '*': + { + if (blkComment) { + ch = buffer.read(); + cnt++; + if (ch == '/') { + blkComment = false; + offsets[1] = cnt; + blockComments.add(offsets); + } + } + cnt++; + break; + } + default: + { + cnt++; + break; + } + } + } + } catch (IOException e) { + // ignore errors + } + } + + /** A simple fuzzy scanner for SQL */ + public class SqlScanner { + protected Map reservedKeywords = new HashMap<>(); + protected Map reservedFunctionNames = new HashMap<>(); + protected StringBuilder fBuffer = new StringBuilder(); + protected String fDoc; + protected int fPos; + protected int fEnd; + protected int fStartToken; + protected boolean fEofSeen = false; + + private static final List DEFAULT_FUNCTIONS = + List.of( + "getdate", + "case", + "convert", + "left", + "right", + "isnumeric", + "isdate", + "isnumber", + "number", + "finally", + "cast", + "var", + "fetch_status", + "isnull", + "charindex", + "difference", + "len", + "nchar", + "quotename", + "replicate", + "reverse", + "str", + "stuff", + "unicode", + "ascii", + "char", + "to_char", + "to_date", + "to_number", + "nvl", + "sysdate", + "corr", + "count", + "grouping", + "max", + "min", + "stdev", + "sum", + "concat", + "length", + "locate", + "ltrim", + "posstr", + "repeat", + "replace", + "rtrim", + "soundex", + "space", + "substr", + "substring", + "trunc", + "nextval", + "currval", + "getclobval", + "char_length", + "compare", + "patindex", + "sortkey", + "uscalar", + "current_date", + "current_time", + "current_timestamp", + "current_user", + "session_user", + "system_user", + "curdate", + "curtime", + "database", + "now", + "sysdate", + "today", + "user", + "version", + "coalesce", + "nullif", + "octet_length", + "datalength", + "decode", + "greatest", + "ifnull", + "least", + "char_length", + "character_length", + "collate", + "concatenate", + "like", + "lower", + "position", + "translate", + "upper", + "char_octet_length", + "character_maximum_length", + "character_octet_length", + "ilike", + "initcap", + "instr", + "lcase", + "lpad", + "patindex", + "rpad", + "ucase", + "bit_length", + "abs", + "asin", + "atan", + "ceiling", + "cos", + "cot", + "exp", + "floor", + "ln", + "log", + "log10", + "mod", + "pi", + "power", + "rand", + "round", + "sign", + "sin", + "sqrt", + "tan", + "trunc", + "extract", + "interval", + "overlaps", + "adddate", + "age", + "date_add", + "dateformat", + "date_part", + "date_sub", + "datediff", + "dateadd", + "datename", + "datepart", + "day", + "dayname", + "dayofmonth", + "dayofweek", + "dayofyear", + "hour", + "last_day", + "minute", + "month", + "month_between", + "monthname", + "next_day", + "second", + "sub_date", + "week", + "year", + "dbo", + "log", + "objectproperty"); + + private static final List KEYWORDS = + List.of( + "create", + "procedure", + "as", + "set", + "nocount", + "on", + "declare", + "varchar", + "print", + "table", + "int", + "tintytext", + "select", + "from", + "where", + "and", + "or", + "insert", + "into", + "cursor", + "read_only", + "for", + "open", + "fetch", + "next", + "end", + "deallocate", + "table", + "drop", + "exec", + "begin", + "close", + "update", + "delete", + "truncate", + "left", + "inner", + "outer", + "cross", + "join", + "union", + "all", + "float", + "when", + "nolock", + "with", + "false", + "datetime", + "dare", + "time", + "hour", + "array", + "minute", + "second", + "millisecond", + "view", + "function", + "catch", + "const", + "continue", + "compute", + "browse", + "option", + "date", + "default", + "do", + "raw", + "auto", + "explicit", + "xmldata", + "elements", + "binary", + "base64", + "read", + "outfile", + "asc", + "desc", + "else", + "eval", + "escape", + "having", + "limit", + "offset", + "of", + "intersect", + "except", + "using", + "variance", + "specific", + "language", + "body", + "returns", + "specific", + "deterministic", + "not", + "external", + "action", + "reads", + "static", + "inherit", + "called", + "order", + "group", + "by", + "natural", + "full", + "exists", + "between", + "some", + "any", + "unique", + "match", + "value", + "limite", + "minus", + "references", + "grant", + "on", + "top", + "index", + "bigint", + "text", + "char", + "use", + "move", + "exec", + "init", + "name", + "noskip", + "skip", + "noformat", + "format", + "stats", + "disk", + "from", + "to", + "rownum", + "alter", + "add", + "remove", + "move", + "alter", + "add", + "remove", + "lineno", + "modify", + "if", + "else", + "in", + "is", + "new", + "Number", + "null", + "string", + "switch", + "this", + "then", + "throw", + "true", + "false", + "try", + "return", + "with", + "while", + "start", + "connect", + "optimize", + "first", + "only", + "rows", + "sequence", + "blob", + "clob", + "image", + "binary", + "column", + "decimal", + "distinct", + "primary", + "key", + "timestamp", + "varbinary", + "nvarchar", + "nchar", + "longnvarchar", + "nclob", + "numeric", + "constraint", + "dbcc", + "backup", + "bit", + "clustered", + "pad_index", + "off", + "statistics_norecompute", + "ignore_dup_key", + "allow_row_locks", + "allow_page_locks", + "textimage_on", + "double", + "rollback", + "tran", + "transaction", + "commit"); + + public SqlScanner(List functionNames) { + addKeywords(KEYWORDS); + addFunctionNames(functionNames); + + // Use default functions + if (reservedFunctionNames.isEmpty()) { + addFunctionNames(SqlScanner.DEFAULT_FUNCTIONS); + } + } + + public void addKeywords(List keywords) { + if (Utils.isEmpty(keywords)) { + return; + } + keywords.forEach(name -> reservedKeywords.put(name, Integer.valueOf(KEY))); + } + + public void addFunctionNames(List functionNames) { + if (Utils.isEmpty(functionNames)) { + return; + } + functionNames.forEach(name -> reservedFunctionNames.put(name, Integer.valueOf(FUNCTION))); + } + + /** Returns the ending location of the current token in the document. */ + public final int getLength() { + return fPos - fStartToken; + } + + /** Returns the starting location of the current token in the document. */ + public final int getStartOffset() { + return fStartToken; + } + + /** Returns the next lexical token in the document. */ + public int nextToken() { + int c; + fStartToken = fPos; + while (true) { + switch (c = read()) { + case EOF: + return EOF; + case '/': // comment + c = read(); + if (c == '/') { + while (true) { + c = read(); + if ((c == EOF) || (c == EOL)) { + unread(c); + return COMMENT; + } + } + } + unread(c); + return SYMBOL; + case '-': // comment + c = read(); + if (c == '-') { + while (true) { + c = read(); + if ((c == EOF) || (c == EOL)) { + unread(c); + return COMMENT; + } + } + } + unread(c); + return SYMBOL; + + case '\'': // char const + for (; ; ) { + c = read(); + switch (c) { + case '\'': + return STRING; + case EOF: + unread(c); + return STRING; + case '\\': + c = read(); + break; + default: + break; + } + } + + case '"': // string + for (; ; ) { + c = read(); + switch (c) { + case '"': + return STRING; + case EOF: + unread(c); + return STRING; + case '\\': + c = read(); + break; + default: + break; + } + } + + case '(', ')', '*', '+', '%', '=', '>', '<', '^', '!', ':', '.', ';': + return SYMBOL; + + case '?': + return PARAM; + + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + do { + c = read(); + } while (Character.isDigit((char) c)); + unread(c); + return NUMBER; + default: + if (Character.isWhitespace((char) c)) { + do { + c = read(); + } while (Character.isWhitespace((char) c)); + unread(c); + return WHITE; + } + if (Character.isJavaIdentifierStart((char) c)) { + fBuffer.setLength(0); + do { + fBuffer.append((char) c); + c = read(); + } while (Character.isJavaIdentifierPart((char) c)); + unread(c); + // Keywords and functions are not case-sensitive + String name = fBuffer.toString(); + if (c == '(') { + Integer token = reservedFunctionNames.get(name); + if (token != null) { + return token.intValue(); + } + } else { + Integer token = reservedKeywords.get(name); + if (token != null) { + return token.intValue(); + } + } + return WORD; + } + return OTHER; + } + } + } + + /** Returns next character. */ + protected int read() { + if (fPos <= fEnd) { + return fDoc.charAt(fPos++); + } + return EOF; + } + + public void setRange(String text) { + fDoc = text.toLowerCase(); + fPos = 0; + fEnd = fDoc.length() - 1; + } + + protected void unread(int c) { + if (c != EOF) { + fPos--; + } + } + } + + /** + * @return the scriptStatements + */ + public List getScriptStatements() { + return scriptStatements; + } + + /** + * @param scriptStatements the scriptStatements to set + */ + public void setScriptStatements(List scriptStatements) { + this.scriptStatements = scriptStatements; + } +} diff --git a/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/StyleAttribute.java b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/StyleAttribute.java new file mode 100644 index 0000000000..59f3220845 --- /dev/null +++ b/ui/src/main/java/org/apache/hop/ui/core/widget/highlight/StyleAttribute.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hop.ui.core.widget.highlight; + +import java.util.Objects; +import org.eclipse.swt.graphics.Color; + +public class StyleAttribute { + + /** Foreground color */ + private Color foreground; + + /** The font style */ + private int style; + + /** Cached hash code. */ + private int hash; + + /** + * Creates a text attribute with the given colors and style. + * + * @param foreground the foreground color, null if none + * @param style the style, may be SWT.NORMAL, SWT.ITALIC or SWT.BOLD + */ + public StyleAttribute(Color foreground, int style) { + this.foreground = foreground; + this.style = style; + } + + @Override + public boolean equals(Object object) { + + if (object == this) return true; + + if (!(object instanceof StyleAttribute)) return false; + StyleAttribute a = (StyleAttribute) object; + + return (a.style == style && equals(a.foreground, foreground)); + } + + /** + * Returns whether the two given objects are equal. + * + * @param o1 the first object, can be null + * @param o2 the second object, can be null + * @return true if the given objects are equals + * @since 2.0 + */ + private boolean equals(Object o1, Object o2) { + if (o1 != null) return o1.equals(o2); + return (o2 == null); + } + + @Override + public int hashCode() { + if (hash == 0) { + hash = Objects.hash(foreground, style); + } + return hash; + } + + /** + * Returns the attribute's foreground color. + * + * @return the attribute's foreground color or null if not set + */ + public Color getForeground() { + return foreground; + } + + /** + * Returns the attribute's style. + * + * @return the attribute's style + */ + public int getStyle() { + return style; + } +}