Skip to content

Commit c0eca77

Browse files
authored
Proposing a more flexible lexing framework (#3537)
2 parents 8bce18b + a0c4f81 commit c0eca77

12 files changed

Lines changed: 933 additions & 227 deletions

File tree

key.core/src/main/java/de/uka/ilkd/key/proof/Proof.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1252,7 +1252,7 @@ public StrategyFactory getActiveStrategyFactory() {
12521252
* @return null or the previous data
12531253
* @see #register(Object, Class)
12541254
*/
1255-
public <T> T lookup(Class<T> service) {
1255+
public <T> @Nullable T lookup(Class<T> service) {
12561256
try {
12571257
if (userData == null) {
12581258
return null;

key.core/src/main/java/de/uka/ilkd/key/speclang/jml/JMLUtils.java

Lines changed: 0 additions & 88 deletions
This file was deleted.

key.core/src/main/java/de/uka/ilkd/key/speclang/njml/JmlMarkerDecision.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,15 @@ private boolean consume(String str) {
129129
return false;
130130
}
131131

132+
/**
133+
* Given a string of conditions of a JML comment, that method decides whether the conditions are
134+
* met.
135+
*
136+
* @param foundKeys a string of conditions, e.g., {@code "+key+esc-float"}. Should not contain
137+
* whitespaces.
138+
* @return true whether the given conditions are met and the comment should be considered as
139+
* active.
140+
*/
132141
public boolean isActiveJmlSpec(String foundKeys) {
133142
if (foundKeys.isEmpty()) {
134143
// a JML annotation with no keys is always included,

key.core/src/test/java/de/uka/ilkd/key/speclang/jml/JMLUtilsTest.java

Lines changed: 0 additions & 60 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* This file is part of KeY - https://key-project.org
2+
* KeY is licensed under the GNU General Public License Version 2
3+
* SPDX-License-Identifier: GPL-2.0-only */
4+
package de.uka.ilkd.key.speclang.jml;
5+
6+
import de.uka.ilkd.key.speclang.njml.JmlMarkerDecision;
7+
8+
import org.junit.jupiter.api.Test;
9+
10+
import static org.junit.jupiter.api.Assertions.assertFalse;
11+
import static org.junit.jupiter.api.Assertions.assertTrue;
12+
13+
14+
public class JmlMarkerDecisionTest {
15+
16+
@Test
17+
public void testIsActiveJmlSpec() {
18+
JmlMarkerDecision dec = new JmlMarkerDecision(null);
19+
assertFalse(dec.isActiveJmlSpec("+ESC"));
20+
assertFalse(dec.isActiveJmlSpec("+a+b+c"));
21+
assertFalse(dec.isActiveJmlSpec("+a"));
22+
assertFalse(dec.isActiveJmlSpec("-key+key"));
23+
assertFalse(dec.isActiveJmlSpec("-"));
24+
assertFalse(dec.isActiveJmlSpec("+"));
25+
assertFalse(dec.isActiveJmlSpec("+ke y"));
26+
27+
assertTrue(dec.isActiveJmlSpec("+key-a b"));
28+
assertTrue(dec.isActiveJmlSpec("+a+key"));
29+
assertTrue(dec.isActiveJmlSpec("+key"));
30+
assertTrue(dec.isActiveJmlSpec("+key"));
31+
assertTrue(dec.isActiveJmlSpec("+KEY"));
32+
assertTrue(dec.isActiveJmlSpec("+KEY"));
33+
assertTrue(dec.isActiveJmlSpec(""));
34+
}
35+
}

key.ui/src/main/java/de/uka/ilkd/key/gui/IssueDialog.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
import de.uka.ilkd.key.gui.actions.EditSourceFileAction;
2626
import de.uka.ilkd.key.gui.actions.SendFeedbackAction;
2727
import de.uka.ilkd.key.gui.configuration.Config;
28-
import de.uka.ilkd.key.gui.sourceview.JavaDocument;
28+
import de.uka.ilkd.key.gui.sourceview.JavaJMLEditorLexer;
29+
import de.uka.ilkd.key.gui.sourceview.KeYEditorLexer;
30+
import de.uka.ilkd.key.gui.sourceview.SourceHighlightDocument;
2931
import de.uka.ilkd.key.gui.sourceview.TextLineNumber;
3032
import de.uka.ilkd.key.gui.utilities.GuiUtilities;
3133
import de.uka.ilkd.key.gui.utilities.SquigglyUnderlinePainter;
@@ -687,7 +689,9 @@ private void updatePreview(PositionedIssueString issue) {
687689
}), "\n");
688690

689691
if (isJava(uri.getPath())) {
690-
showJavaSourceCode(source);
692+
showSourceCode(source, new JavaJMLEditorLexer());
693+
} else if (isKeY(uri.getPath())) {
694+
showSourceCode(source, new KeYEditorLexer());
691695
} else {
692696
txtSource.setText(source);
693697
}
@@ -709,9 +713,9 @@ private void updateStackTrace(PositionedIssueString issue) {
709713
txtStacktrace.setText(issue.getAdditionalInfo());
710714
}
711715

712-
private void showJavaSourceCode(String source) {
716+
private void showSourceCode(String source, SourceHighlightDocument.EditorLexer lexer) {
713717
try {
714-
JavaDocument doc = new JavaDocument();
718+
SourceHighlightDocument doc = new SourceHighlightDocument(lexer);
715719
txtSource.setDocument(doc);
716720
doc.insertString(0, source, new SimpleAttributeSet());
717721
} catch (BadLocationException e) {
@@ -752,6 +756,10 @@ private boolean isJava(String fileName) {
752756
return fileName != null && fileName.endsWith(".java");
753757
}
754758

759+
private boolean isKeY(String fileName) {
760+
return fileName != null && (fileName.endsWith(".key") || fileName.endsWith(".proof"));
761+
}
762+
755763
public static int getOffsetFromLineColumn(String source, Position pos) {
756764
// Position has 1-based line and column, we need them 0-based
757765
return getOffsetFromLineColumn(source, pos.line() - 1, pos.column() - 1);

key.ui/src/main/java/de/uka/ilkd/key/gui/actions/EditSourceFileAction.java

Lines changed: 26 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,12 @@
66
import java.awt.*;
77
import java.awt.event.ActionEvent;
88
import java.awt.event.ActionListener;
9-
import java.awt.event.KeyAdapter;
10-
import java.awt.event.KeyEvent;
119
import java.io.File;
1210
import java.io.IOException;
1311
import java.net.URI;
1412
import java.nio.file.Files;
1513
import java.nio.file.Paths;
1614
import java.util.Optional;
17-
import java.util.Timer;
18-
import java.util.TimerTask;
1915
import javax.swing.*;
2016
import javax.swing.border.TitledBorder;
2117
import javax.swing.text.BadLocationException;
@@ -25,7 +21,9 @@
2521
import de.uka.ilkd.key.gui.MainWindow;
2622
import de.uka.ilkd.key.gui.configuration.Config;
2723
import de.uka.ilkd.key.gui.fonticons.IconFactory;
28-
import de.uka.ilkd.key.gui.sourceview.JavaDocument;
24+
import de.uka.ilkd.key.gui.sourceview.JavaJMLEditorLexer;
25+
import de.uka.ilkd.key.gui.sourceview.KeYEditorLexer;
26+
import de.uka.ilkd.key.gui.sourceview.SourceHighlightDocument;
2927
import de.uka.ilkd.key.gui.sourceview.TextLineNumber;
3028
import de.uka.ilkd.key.java.Position;
3129
import de.uka.ilkd.key.parser.Location;
@@ -137,65 +135,35 @@ public void addNotify() {
137135
textAreaGoto(this, location.getPosition());
138136
}
139137
};
140-
Optional<URI> file = location.getFileURI();
141-
String source = IOUtil.readFrom(file.orElse(null));
138+
Optional<URI> fileOpt = location.getFileURI();
139+
if (fileOpt.isEmpty()) {
140+
JTextPane jTextPane = new JTextPane();
141+
jTextPane.setText("No file location available");
142+
return jTextPane;
143+
}
144+
145+
URI file = fileOpt.get();
146+
String source = IOUtil.readFrom(file);
142147
// workaround for #1641: replace all carriage returns, since JavaDocument can currently
143148
// not handle them
144149
source = source != null ? source.replace("\r", "") : "";
145150

146-
if (file.isPresent() && file.get().toString().endsWith(".java")) {
147-
JavaDocument doc = new JavaDocument();
148-
try {
149-
doc.insertString(0, source, new SimpleAttributeSet());
150-
} catch (BadLocationException e) {
151-
LOGGER.warn("Failed insert string", e);
152-
}
153-
textPane.setDocument(doc);
154-
155-
// when no char is inserted for the specified interval, refresh the syntax highlighting
156-
// note: When other keys are pressed or held down (e.g. arrow keys) nothing is done.
157-
textPane.addKeyListener(new KeyAdapter() {
158-
private Timer timer = new Timer();
159-
160-
@Override
161-
public void keyTyped(KeyEvent e) {
162-
restartTimer();
163-
}
164-
165-
private void restartTimer() {
166-
timer.cancel();
167-
timer = new Timer();
168-
final TimerTask task = new TimerTask() {
169-
@Override
170-
public void run() {
171-
// synchronized to avoid inserting chars during document updating
172-
synchronized (textPane) {
173-
int pos = textPane.getCaretPosition();
174-
int start = textPane.getSelectionStart();
175-
int end = textPane.getSelectionEnd();
176-
String content = textPane.getText();
177-
try {
178-
// creating a completely new document seems to be more than
179-
// necessary, but works well enough for the moment
180-
JavaDocument newDoc = new JavaDocument();
181-
newDoc.insertString(0, content, new SimpleAttributeSet());
182-
textPane.setDocument(newDoc);
183-
textPane.setCaretPosition(pos);
184-
textPane.setSelectionStart(start);
185-
textPane.setSelectionEnd(end);
186-
} catch (BadLocationException ex) {
187-
LOGGER.warn("Failed update document", ex);
188-
}
189-
textPane.repaint();
190-
}
191-
}
192-
};
193-
timer.schedule(task, SYNTAX_HIGHLIGHTING_REFRESH_INTERVAL);
194-
}
195-
});
151+
SourceHighlightDocument.EditorLexer lexer;
152+
if (file.toString().endsWith(".java")) {
153+
lexer = new JavaJMLEditorLexer();
154+
} else if (file.toString().endsWith(".key") || file.toString().endsWith(".proof")) {
155+
lexer = new KeYEditorLexer();
196156
} else {
197-
textPane.setText(source);
157+
lexer = SourceHighlightDocument.TRIVIAL_LEXER;
158+
}
159+
160+
SourceHighlightDocument doc = new SourceHighlightDocument(lexer);
161+
try {
162+
doc.insertString(0, source, new SimpleAttributeSet());
163+
} catch (BadLocationException e) {
164+
LOGGER.warn("Failed insert string", e);
198165
}
166+
textPane.setDocument(doc);
199167

200168
Font font = UIManager.getFont(Config.KEY_FONT_SEQUENT_VIEW);
201169
if (font == null) {

key.ui/src/main/java/de/uka/ilkd/key/gui/sourceview/JavaDocument.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
import javax.swing.text.*;
1212

1313
import de.uka.ilkd.key.gui.colors.ColorSettings;
14-
15-
import static de.uka.ilkd.key.speclang.jml.JMLUtils.isJmlCommentStarter;
14+
import de.uka.ilkd.key.speclang.njml.JmlMarkerDecision;
1615

1716
/**
1817
* This document performs syntax highlighting when strings are inserted. However, only inserting the
@@ -321,8 +320,10 @@ private void checkAt() {
321320
|| state == CommentState.JML_ANNOTATION_LINE) {
322321
boolean lineComment = state == CommentState.JML_ANNOTATION_LINE;
323322
state = CommentState.NO;
324-
String features = token.substring(2); // cut-off '//' or '/*'
325-
if (isJmlCommentStarter(features)) {
323+
String features = token.substring(2, token.length() - 1); // cut-off '//' or '/*' and
324+
// '@'
325+
var jmlMarkerDecision = new JmlMarkerDecision(null);
326+
if (jmlMarkerDecision.isActiveJmlSpec(features)) {
326327
mode = lineComment ? Mode.LINE_JML : Mode.JML;
327328
} else {
328329
mode = lineComment ? Mode.LINE_COMMENT : Mode.COMMENT;

0 commit comments

Comments
 (0)