From 184fe9c2133cdd09345dcf544a105511f0cbfb5b Mon Sep 17 00:00:00 2001 From: rusefillc Date: Thu, 14 Oct 2021 14:46:05 -0400 Subject: [PATCH] Whatever we call it, no matter how we do it - we need live data / remote view into rusEFI actual state #3353 progress --- .../rusefi/livedata/LiveDataParserPanel.java | 146 ++++++++++++++++++ .../java/com/rusefi/ui/livedata/Range.java | 29 ++++ .../rusefi/ui/livedata/SourceCodePainter.java | 7 + .../ui/livedata/VariableValueSource.java | 5 + .../livedata/LiveDataParserSandbox.java | 27 ++++ .../ui/livedata/LiveDataParserTest.java | 95 ++---------- .../rusefi/ui/livedata/SourceReaderTest.java | 16 +- 7 files changed, 232 insertions(+), 93 deletions(-) create mode 100644 java_console/ui/src/main/java/com/rusefi/livedata/LiveDataParserPanel.java create mode 100644 java_console/ui/src/main/java/com/rusefi/ui/livedata/Range.java create mode 100644 java_console/ui/src/main/java/com/rusefi/ui/livedata/SourceCodePainter.java create mode 100644 java_console/ui/src/main/java/com/rusefi/ui/livedata/VariableValueSource.java create mode 100644 java_console/ui/src/test/java/com/rusefi/livedata/LiveDataParserSandbox.java diff --git a/java_console/ui/src/main/java/com/rusefi/livedata/LiveDataParserPanel.java b/java_console/ui/src/main/java/com/rusefi/livedata/LiveDataParserPanel.java new file mode 100644 index 0000000000..88cdbd9bc5 --- /dev/null +++ b/java_console/ui/src/main/java/com/rusefi/livedata/LiveDataParserPanel.java @@ -0,0 +1,146 @@ +package com.rusefi.livedata; + +import com.devexperts.logging.Logging; +import com.rusefi.livedata.generated.CPP14Lexer; +import com.rusefi.livedata.generated.CPP14Parser; +import com.rusefi.livedata.generated.CPP14ParserBaseListener; +import com.rusefi.ui.livedata.Range; +import com.rusefi.ui.livedata.SourceCodePainter; +import com.rusefi.ui.livedata.VariableValueSource; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.text.AttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; +import javax.swing.text.StyledDocument; +import java.awt.*; +import java.io.*; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Stack; + +import static com.devexperts.logging.Logging.getLogging; +import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED; +import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED; + +public class LiveDataParserPanel { + private static final Logging log = getLogging(LiveDataParserPanel.class); + + private final JPanel content = new JPanel(new BorderLayout()); + + public LiveDataParserPanel(VariableValueSource valueSource) { + JTextPane text = new JTextPane(); + + JScrollPane rightScrollPane = new JScrollPane(text, + VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED); + + content.add(rightScrollPane); + + try { + String sourceCode = getContent(getClass(), "ac_control.cpp"); + text.setText(sourceCode); + + ParseTree tree = getParseTree(sourceCode); + + StyleContext sc = StyleContext.getDefaultStyleContext(); + + StyledDocument style = text.getStyledDocument(); + AttributeSet oldSet = style.getCharacterElement(0).getAttributes(); + + + applyVariables(valueSource, sourceCode, new SourceCodePainter() { + @Override + public void paint(Color color, Range range) { + + AttributeSet s = sc.addAttribute(oldSet, StyleConstants.Background, color); + style.setCharacterAttributes(range.getStart(), range.getLength(), s, true); + + } + }, tree); + + + } catch (IOException | URISyntaxException e) { + log.warn("Error reading: " + e); + } + } + + public static String getContent(Class clazz, String fileName) throws IOException, URISyntaxException { + URL cpp = clazz.getResource("/c_sources/" + fileName); + String line; + + StringBuilder result = new StringBuilder(); + try (BufferedReader br = new BufferedReader(new FileReader(new File(cpp.toURI())))) { + while ((line = br.readLine()) != null) { + result.append(line + "\n"); + } + } + return result.toString(); + } + + @NotNull + public static ParseTree getParseTree(String sourceCode) throws IOException { + CharStream in = new ANTLRInputStream(new ByteArrayInputStream(sourceCode.getBytes())); + CPP14Parser parser = new CPP14Parser(new CommonTokenStream(new CPP14Lexer(in))); + return parser.translationUnit(); + } + + public static void applyVariables(VariableValueSource valueSource, String s, SourceCodePainter painter, ParseTree tree) { + Stack currentState = new Stack<>(); + currentState.add(Boolean.TRUE); + + new ParseTreeWalker().walk(new CPP14ParserBaseListener() { + @Override + public void enterStatement(CPP14Parser.StatementContext ctx) { + String origin = getOrigin(ctx, s); + System.out.println("enter statement [" + origin + "]"); + } + + @Override + public void enterCondition(CPP14Parser.ConditionContext ctx) { + String conditionVariable = ctx.getText(); + System.out.println("REQUESTING VALUE " + conditionVariable); + System.out.println("exp " + getOrigin(ctx.expression(), s)); + + Boolean state = (Boolean) valueSource.getValue(conditionVariable); + if (state == null) { + // todo: fail on unknown condition variables + return; + } + if (state) { + painter.paint(Color.GREEN, new Range(ctx)); + } else { + painter.paint(Color.RED, new Range(ctx)); + } + } + + @Override + public void enterSelectionStatement(CPP14Parser.SelectionStatementContext ctx) { + super.enterSelectionStatement(ctx); + + System.out.println("Else terminal " + ctx.Else()); + } + + @Override + public void enterJumpStatement(CPP14Parser.JumpStatementContext ctx) { + + } + }, tree); + } + + @NotNull + private static String getOrigin(ParserRuleContext ctx, String s) { + Range range = new Range(ctx); + return s.substring(range.getStart(), range.getStop()); + } + + public JPanel getContent() { + return content; + } +} diff --git a/java_console/ui/src/main/java/com/rusefi/ui/livedata/Range.java b/java_console/ui/src/main/java/com/rusefi/ui/livedata/Range.java new file mode 100644 index 0000000000..7e15a840d2 --- /dev/null +++ b/java_console/ui/src/main/java/com/rusefi/ui/livedata/Range.java @@ -0,0 +1,29 @@ +package com.rusefi.ui.livedata; + +import org.antlr.v4.runtime.ParserRuleContext; + +public class Range { + private final int start; + private final int stop; + + public Range(int start, int stop) { + this.start = start; + this.stop = stop; + } + + public Range(ParserRuleContext context) { + this(context.start.getStartIndex(), context.stop.getStopIndex() + 1); + } + + public int getStart() { + return start; + } + + public int getStop() { + return stop; + } + + public int getLength() { + return stop - start; + } +} diff --git a/java_console/ui/src/main/java/com/rusefi/ui/livedata/SourceCodePainter.java b/java_console/ui/src/main/java/com/rusefi/ui/livedata/SourceCodePainter.java new file mode 100644 index 0000000000..e06b626915 --- /dev/null +++ b/java_console/ui/src/main/java/com/rusefi/ui/livedata/SourceCodePainter.java @@ -0,0 +1,7 @@ +package com.rusefi.ui.livedata; + +import java.awt.*; + +public interface SourceCodePainter { + void paint(Color color, Range range); +} diff --git a/java_console/ui/src/main/java/com/rusefi/ui/livedata/VariableValueSource.java b/java_console/ui/src/main/java/com/rusefi/ui/livedata/VariableValueSource.java new file mode 100644 index 0000000000..c318101aa3 --- /dev/null +++ b/java_console/ui/src/main/java/com/rusefi/ui/livedata/VariableValueSource.java @@ -0,0 +1,5 @@ +package com.rusefi.ui.livedata; + +public interface VariableValueSource { + Object getValue(String name); +} diff --git a/java_console/ui/src/test/java/com/rusefi/livedata/LiveDataParserSandbox.java b/java_console/ui/src/test/java/com/rusefi/livedata/LiveDataParserSandbox.java new file mode 100644 index 0000000000..68ba0222a2 --- /dev/null +++ b/java_console/ui/src/test/java/com/rusefi/livedata/LiveDataParserSandbox.java @@ -0,0 +1,27 @@ +package com.rusefi.livedata; + +import com.rusefi.core.ValueSource; +import com.rusefi.ui.livedata.LiveDataParserTest; +import com.rusefi.ui.livedata.VariableValueSource; +import com.rusefi.ui.util.FrameHelper; + +import java.util.Map; +import java.util.TreeMap; + +public class LiveDataParserSandbox { + public static void main(String[] args) { + Map values = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + values.put("engineTooSlow", Boolean.TRUE); + values.put("engineTooFast", Boolean.FALSE); + + VariableValueSource valueSource = new VariableValueSource() { + @Override + public Object getValue(String name) { + return values.get(name); + } + }; + + + new FrameHelper().showFrame(new LiveDataParserPanel(valueSource).getContent()); + } +} diff --git a/java_console/ui/src/test/java/com/rusefi/ui/livedata/LiveDataParserTest.java b/java_console/ui/src/test/java/com/rusefi/ui/livedata/LiveDataParserTest.java index 4265fbb741..9ce0f7e7e1 100644 --- a/java_console/ui/src/test/java/com/rusefi/ui/livedata/LiveDataParserTest.java +++ b/java_console/ui/src/test/java/com/rusefi/ui/livedata/LiveDataParserTest.java @@ -1,11 +1,6 @@ package com.rusefi.ui.livedata; -import com.rusefi.livedata.generated.CPP14Lexer; -import com.rusefi.livedata.generated.CPP14Parser; -import com.rusefi.livedata.generated.CPP14ParserBaseListener; -import org.antlr.v4.runtime.ANTLRInputStream; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.CommonTokenStream; +import com.rusefi.livedata.LiveDataParserPanel; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTreeWalker; @@ -13,11 +8,8 @@ import org.jetbrains.annotations.NotNull; import org.junit.Test; import java.awt.*; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.util.HashMap; import java.util.Map; -import java.util.Stack; import java.util.TreeMap; public class LiveDataParserTest { @@ -27,14 +19,13 @@ public class LiveDataParserTest { values.put("engineTooSlow", Boolean.TRUE); values.put("engineTooFast", Boolean.FALSE); - ValueSource valueSource = new ValueSource() { + VariableValueSource valueSource = new VariableValueSource() { @Override public Object getValue(String name) { return values.get(name); } }; - String s = "bool AcState::getAcState(DECLARE_ENGINE_PARAMETER_SIGNATURE) {\n" + "\tauto rpm = Sensor::getOrZero(SensorType::Rpm);\n" + "\n" + @@ -51,85 +42,19 @@ public class LiveDataParserTest { "\t} \n " + "return ff;\n" + "}"; - CharStream in = new ANTLRInputStream(new ByteArrayInputStream(s.getBytes())); - CPP14Parser parser = new CPP14Parser(new CommonTokenStream(new CPP14Lexer(in))); - - ParseTree tree = parser.translationUnit(); + SourceCodePainter painter = new SourceCodePainter() { + @Override + public void paint(Color color, Range range) { + System.out.println("paint " + color + " " + range); + } + }; + ParseTree tree = LiveDataParserPanel.getParseTree(s); new ParseTreeWalker().walk(new PrintCPP14ParserListener(), tree); - Stack currentState = new Stack<>(); - currentState.add(Boolean.TRUE); + LiveDataParserPanel.applyVariables(valueSource, s, painter, tree); - new ParseTreeWalker().walk(new CPP14ParserBaseListener() { - @Override - public void enterStatement(CPP14Parser.StatementContext ctx) { - String origin = getOrigin(ctx, s); - System.out.println("enter statement [" + origin + "]"); - } - - @Override - public void enterCondition(CPP14Parser.ConditionContext ctx) { - String conditionVariable = ctx.getText(); - System.out.println("REQUESTING VALUE " + conditionVariable); - System.out.println("exp " + getOrigin(ctx.expression(), s)); - - Boolean state = (Boolean) valueSource.getValue(conditionVariable); - if (state == null) { - // todo: fail on unknown condition variables - return; - } - if (state) { - //paint(Color.GREEN, ctx.) - } - } - - @Override - public void enterSelectionStatement(CPP14Parser.SelectionStatementContext ctx) { - super.enterSelectionStatement(ctx); - - System.out.println("Else terminal " + ctx.Else()); - } - - @Override - public void enterJumpStatement(CPP14Parser.JumpStatementContext ctx) { - - } - }, tree); - - } - - @NotNull - private String getOrigin(ParserRuleContext ctx, String s) { - Range range = new Range(ctx); - return s.substring(range.start, range.stop); - } - - interface ValueSource { - Object getValue(String name); - } - - static class Range { - private final int start; - private final int stop; - - public Range(int start, int stop) { - this.start = start; - this.stop = stop; - } - - public Range(ParserRuleContext context) { - this(context.start.getStartIndex(), context.stop.getStopIndex() + 1); - } - - public int getStart() { - return start; - } - - public int getStop() { - return stop; - } } } diff --git a/java_console/ui/src/test/java/com/rusefi/ui/livedata/SourceReaderTest.java b/java_console/ui/src/test/java/com/rusefi/ui/livedata/SourceReaderTest.java index 0bf8d52660..07efb95c01 100644 --- a/java_console/ui/src/test/java/com/rusefi/ui/livedata/SourceReaderTest.java +++ b/java_console/ui/src/test/java/com/rusefi/ui/livedata/SourceReaderTest.java @@ -1,20 +1,20 @@ package com.rusefi.ui.livedata; +import com.rusefi.livedata.LiveDataParserPanel; import org.junit.Test; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; +import java.io.*; import java.net.URISyntaxException; -import java.net.URL; import static org.junit.Assert.assertNotNull; public class SourceReaderTest { @Test - public void testResourceLocated() throws URISyntaxException, FileNotFoundException { - URL cpp = getClass().getResource("/c_sources/ac_control.cpp"); - assertNotNull(cpp); - new FileReader(new File(cpp.toURI())); + public void testResourceLocated() throws URISyntaxException, IOException { + String fileName = "ac_control.cpp"; + String content = LiveDataParserPanel.getContent(getClass(), fileName); + assertNotNull(content); + } + }