From ee890064cf873613c39241f0a30ab202b2367bac Mon Sep 17 00:00:00 2001 From: Gilles Querret Date: Sun, 31 Oct 2021 04:56:06 +0100 Subject: [PATCH] Macro references now have exact start and end position --- .../IPreprocessorEventListener.java | 4 +- .../prorefactor/macrolevel/IncludeRef.java | 8 +-- .../org/prorefactor/macrolevel/MacroRef.java | 25 ++++++--- .../prorefactor/macrolevel/NamedMacroRef.java | 4 +- .../macrolevel/PreprocessorEventListener.java | 10 ++-- .../java/org/prorefactor/proparse/Lexer.java | 21 ++++---- .../org/prorefactor/core/MacroGraphTest.java | 52 +++++++++++++++++-- .../core/PreprocessorDirectiveTest.java | 22 +++++--- .../prorefactor/proparse/TokenListTest.java | 2 +- .../data/preprocessor/preprocessor02.p | 5 +- .../data/preprocessor/preprocessor15.p | 4 +- .../data/preprocessor/preprocessor18.p | 2 +- 12 files changed, 112 insertions(+), 47 deletions(-) diff --git a/proparse/src/main/java/org/prorefactor/macrolevel/IPreprocessorEventListener.java b/proparse/src/main/java/org/prorefactor/macrolevel/IPreprocessorEventListener.java index e9e416b71..b952d142f 100644 --- a/proparse/src/main/java/org/prorefactor/macrolevel/IPreprocessorEventListener.java +++ b/proparse/src/main/java/org/prorefactor/macrolevel/IPreprocessorEventListener.java @@ -20,9 +20,9 @@ * analyze-* statements, ... */ public interface IPreprocessorEventListener { - void macroRef(int line, int column, String macroName); + void macroRef(int line, int column, int endLine, int endColumn, String macroName); void macroRefEnd(); - void include(int line, int column, int currentFile, String incFile); + void include(int line, int column, int endLine, int endColumn, int currentFile, String incFile); void includeArgument(String argName, String value, boolean undefined); void includeEnd(); void define(int line, int column, String name, String value, MacroDefinitionType type); diff --git a/proparse/src/main/java/org/prorefactor/macrolevel/IncludeRef.java b/proparse/src/main/java/org/prorefactor/macrolevel/IncludeRef.java index c38f4b367..165bf8bf2 100644 --- a/proparse/src/main/java/org/prorefactor/macrolevel/IncludeRef.java +++ b/proparse/src/main/java/org/prorefactor/macrolevel/IncludeRef.java @@ -28,12 +28,12 @@ public class IncludeRef extends MacroRef { private int fileIndex; private boolean usesNamedArgs; - public IncludeRef(MacroRef parent, int line, int column) { - super(parent, line, column); + public IncludeRef(MacroRef parent, int line, int column, int endLine, int endColumn) { + super(parent, line, column, endLine, endColumn); } - public IncludeRef(MacroRef parent, int line, int column, int fileIndex) { - super(parent, line, column); + public IncludeRef(MacroRef parent, int line, int column, int endLine, int endColumn, int fileIndex) { + super(parent, line, column, endLine, endColumn); this.fileIndex = fileIndex; } diff --git a/proparse/src/main/java/org/prorefactor/macrolevel/MacroRef.java b/proparse/src/main/java/org/prorefactor/macrolevel/MacroRef.java index 45b4efd37..b7ff9ea3e 100644 --- a/proparse/src/main/java/org/prorefactor/macrolevel/MacroRef.java +++ b/proparse/src/main/java/org/prorefactor/macrolevel/MacroRef.java @@ -29,14 +29,18 @@ public abstract class MacroRef implements MacroEvent { private final MacroRef parent; private final int refColumn; private final int refLine; + private final int refEndLine; + private final int refEndColumn; /** A list of macro references and defines that are in this macro's source */ public final List macroEventList = new ArrayList<>(); - public MacroRef(MacroRef parent, int line, int column) { + MacroRef(MacroRef parent, int line, int column, int endLine, int endColumn) { this.parent = parent; this.refLine = line; this.refColumn = column; + this.refEndLine = endLine; + this.refEndColumn = endColumn; } @Override @@ -52,15 +56,22 @@ public int getColumn() { return refColumn; } + public int getEndLine() { + return refEndLine; + } + + public int getEndColumn() { + return refEndColumn; + } + /** - * Find external macro references. An external macro is an include file, a &GLOBAL or a &SCOPED from another - * file, and include args. + * Find external macro references. An external macro is an include file, a &GLOBAL or a &SCOPED from + * another file, and include args. * - * TODO: (Jan 26) This doesn't seem right to me anymore. An &UNDEFINE only affects the local scope. If re-implemented - * after building a pseudoprocessor, consider dropping this. &UNDEFINE of a &GLOBAL or of a &SCOPED from another file - * is considered a reference. &UNDEFINE of an include argument is considered a reference. + * &UNDEFINE of a &GLOBAL or of a &SCOPED from another file is considered a reference. &UNDEFINE of an + * include argument is considered a reference. * - * The subroutine is recursive, because a local define may incur an external reference! + * The subroutine is recursive, because a local define may incur an external reference. * * @return An array of objects: MacroRef and MacroDef (for UNDEFINE). */ diff --git a/proparse/src/main/java/org/prorefactor/macrolevel/NamedMacroRef.java b/proparse/src/main/java/org/prorefactor/macrolevel/NamedMacroRef.java index 76185307e..fbbd3a823 100644 --- a/proparse/src/main/java/org/prorefactor/macrolevel/NamedMacroRef.java +++ b/proparse/src/main/java/org/prorefactor/macrolevel/NamedMacroRef.java @@ -21,8 +21,8 @@ public class NamedMacroRef extends MacroRef { private final MacroDef macroDef; - public NamedMacroRef(MacroDef macro, MacroRef parent, int line, int column) { - super(parent, line, column); + public NamedMacroRef(MacroDef macro, MacroRef parent, int line, int column, int endLine, int endColumn) { + super(parent, line, column, endLine, endColumn); this.macroDef = macro; } diff --git a/proparse/src/main/java/org/prorefactor/macrolevel/PreprocessorEventListener.java b/proparse/src/main/java/org/prorefactor/macrolevel/PreprocessorEventListener.java index 5ef75b397..0891d3d0b 100644 --- a/proparse/src/main/java/org/prorefactor/macrolevel/PreprocessorEventListener.java +++ b/proparse/src/main/java/org/prorefactor/macrolevel/PreprocessorEventListener.java @@ -47,7 +47,7 @@ public class PreprocessorEventListener implements IPreprocessorEventListener { private CodeSection currSection; public PreprocessorEventListener() { - root = new IncludeRef(null, 0, 0); + root = new IncludeRef(null, 0, 0, 0, 0); currRef = root; currInclude = root; @@ -91,8 +91,8 @@ public void preproIf(int line, int column, boolean value) { } @Override - public void include(int line, int column, int currentFile, String incFile) { - IncludeRef newRef = new IncludeRef(currRef, line, column, currentFile); + public void include(int line, int column, int endLine, int endColumn, int currentFile, String incFile) { + IncludeRef newRef = new IncludeRef(currRef, line, column, endLine, endColumn, currentFile); scopeStack.addFirst(new Scope(newRef)); currRef.macroEventList.add(newRef); currInclude = newRef; @@ -128,8 +128,8 @@ public void includeEnd() { } @Override - public void macroRef(int line, int column, String macroName) { - NamedMacroRef newRef = new NamedMacroRef(findMacroDef(macroName), currRef, line, column); + public void macroRef(int line, int column, int endLine, int endColumn, String macroName) { + NamedMacroRef newRef = new NamedMacroRef(findMacroDef(macroName), currRef, line, column, endLine, endColumn); currRef.macroEventList.add(newRef); currRef = newRef; } diff --git a/proparse/src/main/java/org/prorefactor/proparse/Lexer.java b/proparse/src/main/java/org/prorefactor/proparse/Lexer.java index 7d6220993..15f7bd575 100644 --- a/proparse/src/main/java/org/prorefactor/proparse/Lexer.java +++ b/proparse/src/main/java/org/prorefactor/proparse/Lexer.java @@ -1547,7 +1547,7 @@ private void ppMacroReference() { ppCurrChar = '{'; currentInput = new InputSource(++sourceCounter, refText.substring(1), refPos.file, refPos.line, refPos.col); currentInclude.addInputSource(currentInput); - prepro.getLstListener().macroRef(refPos.line, refPos.col, "_proparse_"); + prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol, "_proparse_"); } else { // Proparse Directive ppCurrChar = PROPARSE_DIRECTIVE; @@ -1556,7 +1556,7 @@ private void ppMacroReference() { // This will be counted as a source whether picked up here or picked // up as a normal macro ref. ++sourceCounter; - prepro.getLstListener().macroRef(refPos.line, refPos.col, "_proparse_"); + prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol, "_proparse_"); prepro.getLstListener().macroRefEnd(); } } else if ("{*}".equals(refText)) { @@ -1663,16 +1663,13 @@ else if (cp.chars[cp.pos] == '&') { // include '&' named args if (prepro.isLexOnly()) { ppCurrChar = INCLUDE_DIRECTIVE; includeDirectiveText = refText.trim(); - } else - // newInclude() returns false if filename is blank or currently - // "consuming" due to &IF FALSE. - // newInclude() will throw() if file not found or cannot be opened. - if (ppNewInclude(includeFilename)) { - // Unlike currline and currcol, - // currfile is only updated with a push/pop of the input stack. + } else if (ppNewInclude(includeFilename)) { + // ppNewInclude() returns false if filename is blank or currently "consuming" due to &IF FALSE. + // ppNewInclude() will throw UncheckedIOException if file not found or cannot be opened. + // Unlike currline and currcol, currfile is only updated with a push/pop of the input stack. currFile = currentInput.getFileIndex(); currSourceNum = currentInput.getSourceNum(); - prepro.getLstListener().include(refPos.line, refPos.col, currFile, includeFilename); + prepro.getLstListener().include(refPos.line, refPos.col, currLine, currCol, currFile, includeFilename); // Add the arguments to the new include object. int argNum = 1; for (IncludeArg incarg : incArgs) { @@ -1696,12 +1693,12 @@ private void ppNewMacroRef(String macroName, FilePos refPos) { // Using this trick: {{&undefined-argument}{&*}} // it is possible to get line breaks into what we // get here as the macroName. See test data bug15.p and bug15.i. - prepro.getLstListener().macroRef(refPos.line, refPos.col, macroName); + prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol, macroName); ppNewMacroRef2(getArgText(macroName), refPos); } private void ppNewMacroRef(int argNum, FilePos refPos) { - prepro.getLstListener().macroRef(refPos.line, refPos.col, Integer.toString(argNum)); + prepro.getLstListener().macroRef(refPos.line, refPos.col, currLine, currCol, Integer.toString(argNum)); ppNewMacroRef2(getArgText(argNum), refPos); } diff --git a/proparse/src/test/java/org/prorefactor/core/MacroGraphTest.java b/proparse/src/test/java/org/prorefactor/core/MacroGraphTest.java index d263f5428..a8863fa1b 100644 --- a/proparse/src/test/java/org/prorefactor/core/MacroGraphTest.java +++ b/proparse/src/test/java/org/prorefactor/core/MacroGraphTest.java @@ -27,6 +27,7 @@ import org.prorefactor.core.util.UnitTestModule; import org.prorefactor.macrolevel.IncludeRef; import org.prorefactor.macrolevel.MacroEvent; +import org.prorefactor.macrolevel.MacroRef; import org.prorefactor.macrolevel.NamedMacroRef; import org.prorefactor.refactor.RefactorSession; import org.prorefactor.treeparser.ParseUnit; @@ -124,9 +125,46 @@ public void testMacroGraphPosition() { assertFalse(unit.hasSyntaxError()); List list = unit.getMacroGraph().findExternalMacroReferences(); - assertEquals(list.get(0).getPosition().getLine(), 3); - assertEquals(list.get(0).getPosition().getColumn(), 5); - assertEquals(list.get(0).getPosition().getFileNum(), 0); + assertTrue(list.get(0) instanceof IncludeRef); + assertEquals(((MacroRef) list.get(0)).getFileIndex(), 1); + assertEquals(((MacroRef) list.get(0)).getLine(), 3); + assertEquals(((MacroRef) list.get(0)).getColumn(), 5); + assertEquals(((MacroRef) list.get(0)).getEndLine(), 3); + assertEquals(((MacroRef) list.get(0)).getEndColumn(), 40); + assertTrue(list.get(1) instanceof IncludeRef); + assertEquals(((MacroRef) list.get(1)).getFileIndex(), 2); + assertEquals(((MacroRef) list.get(1)).getLine(), 20); + assertEquals(((MacroRef) list.get(1)).getColumn(), 1); + assertEquals(((MacroRef) list.get(1)).getEndLine(), 20); + assertEquals(((MacroRef) list.get(1)).getEndColumn(), 44); + assertTrue(list.get(2) instanceof IncludeRef); + assertEquals(((MacroRef) list.get(2)).getFileIndex(), 3); + assertEquals(((MacroRef) list.get(2)).getLine(), 22); + assertEquals(((MacroRef) list.get(2)).getColumn(), 1); + assertEquals(((MacroRef) list.get(2)).getEndLine(), 22); + assertEquals(((MacroRef) list.get(2)).getEndColumn(), 36); + assertTrue(list.get(3) instanceof IncludeRef); + assertEquals(((MacroRef) list.get(3)).getFileIndex(), 3); + assertEquals(((MacroRef) list.get(3)).getLine(), 28); + assertEquals(((MacroRef) list.get(3)).getColumn(), 1); + assertEquals(((MacroRef) list.get(3)).getEndLine(), 28); + assertEquals(((MacroRef) list.get(3)).getEndColumn(), 36); + + MacroRef ref = (MacroRef) unit.getMacroGraph().macroEventList.get(5); + assertEquals(ref.getLine(), 24); + assertEquals(ref.getEndLine(), 24); + assertEquals(ref.getColumn(), 1); + assertEquals(ref.getEndColumn(), 49); + ref = (MacroRef) unit.getMacroGraph().macroEventList.get(6); + assertEquals(ref.getLine(), 25); + assertEquals(ref.getEndLine(), 25); + assertEquals(ref.getColumn(), 3); + assertEquals(ref.getEndColumn(), 53); + ref = (MacroRef) unit.getMacroGraph().macroEventList.get(7); + assertEquals(ref.getLine(), 26); + assertEquals(ref.getEndLine(), 27); + assertEquals(ref.getColumn(), 1); + assertEquals(ref.getEndColumn(), 1); } @Test @@ -140,6 +178,10 @@ public void testIncludeParameter01() { assertEquals(list.size(), 1); assertTrue(list.get(0) instanceof IncludeRef); IncludeRef ref = (IncludeRef) list.get(0); + assertEquals(ref.getLine(), 1); + assertEquals(ref.getEndLine(), 3); + assertEquals(ref.getColumn(), 1); + assertEquals(ref.getEndColumn(), 44); assertNotNull(ref.getArgNumber(1)); assertEquals(ref.getArgNumber(1).getName(), "param1"); assertEquals(ref.getArgNumber(1).getValue(), "value1"); @@ -160,6 +202,10 @@ public void testIncludeParameter02() { assertEquals(list.size(), 1); assertTrue(list.get(0) instanceof IncludeRef); IncludeRef ref = (IncludeRef) list.get(0); + assertEquals(ref.getLine(), 1); + assertEquals(ref.getEndLine(), 5); + assertEquals(ref.getColumn(), 1); + assertEquals(ref.getEndColumn(), 33); assertNotNull(ref.getArgNumber(1)); assertEquals(ref.getArgNumber(1).getName(), "param1"); assertEquals(ref.getArgNumber(1).getValue(), "value1"); diff --git a/proparse/src/test/java/org/prorefactor/core/PreprocessorDirectiveTest.java b/proparse/src/test/java/org/prorefactor/core/PreprocessorDirectiveTest.java index ace9f7a20..bb36cd5b1 100644 --- a/proparse/src/test/java/org/prorefactor/core/PreprocessorDirectiveTest.java +++ b/proparse/src/test/java/org/prorefactor/core/PreprocessorDirectiveTest.java @@ -27,6 +27,7 @@ import org.prorefactor.core.util.UnitTestModule; import org.prorefactor.macrolevel.IncludeRef; import org.prorefactor.macrolevel.MacroDef; +import org.prorefactor.macrolevel.MacroRef; import org.prorefactor.macrolevel.NamedMacroRef; import org.prorefactor.proparse.antlr4.Proparse; import org.prorefactor.refactor.RefactorSession; @@ -303,6 +304,10 @@ public void test09() { assertTrue(incRef.macroEventList.get(1) instanceof NamedMacroRef); NamedMacroRef nmr = (NamedMacroRef) incRef.macroEventList.get(1); assertEquals(nmr.getMacroDef(), incRef.macroEventList.get(0)); + assertEquals(nmr.getLine(), 4); + assertEquals(nmr.getEndLine(), 4); + assertEquals(nmr.getColumn(), 10); + assertEquals(nmr.getEndColumn(), 17); } @Test @@ -310,12 +315,17 @@ public void test10() { ParseUnit unit = new ParseUnit(new File(SRC_DIR, "preprocessor16.p"), session); unit.parse(); assertFalse(unit.hasSyntaxError()); - IncludeRef incRef = unit.getMacroGraph(); - assertEquals(incRef.macroEventList.size(), 3); - assertTrue(incRef.macroEventList.get(0) instanceof MacroDef); - assertTrue(incRef.macroEventList.get(1) instanceof NamedMacroRef); - NamedMacroRef nmr = (NamedMacroRef) incRef.macroEventList.get(1); - assertEquals(nmr.getMacroDef(), incRef.macroEventList.get(0)); + IncludeRef mainFile = unit.getMacroGraph(); + assertEquals(mainFile.macroEventList.size(), 3); + assertTrue(mainFile.macroEventList.get(0) instanceof MacroDef); + assertTrue(mainFile.macroEventList.get(1) instanceof NamedMacroRef); + NamedMacroRef nmr = (NamedMacroRef) mainFile.macroEventList.get(1); + assertEquals(nmr.getMacroDef(), mainFile.macroEventList.get(0)); + IncludeRef incRef = (IncludeRef) mainFile.macroEventList.get(2); + assertEquals(incRef.getLine(), 6); + assertEquals(incRef.getEndLine(), 6); + assertEquals(incRef.getColumn(), 4); + assertEquals(incRef.getEndColumn(), 36); List nodes = unit.getTopNode().query(ABLNodeType.DEFINE); assertEquals(nodes.size(), 1); // Preprocessor magic... Keywords can start in main file, and end in include file... diff --git a/proparse/src/test/java/org/prorefactor/proparse/TokenListTest.java b/proparse/src/test/java/org/prorefactor/proparse/TokenListTest.java index 1782c99a0..8b38428c9 100644 --- a/proparse/src/test/java/org/prorefactor/proparse/TokenListTest.java +++ b/proparse/src/test/java/org/prorefactor/proparse/TokenListTest.java @@ -42,7 +42,7 @@ public class TokenListTest { private RefactorSession session; @BeforeTest - public void setUp() { + public void setUp() { Injector injector = Guice.createInjector(new UnitTestModule()); session = injector.getInstance(RefactorSession.class); } diff --git a/proparse/src/test/resources/data/preprocessor/preprocessor02.p b/proparse/src/test/resources/data/preprocessor/preprocessor02.p index fa76af014..e6da85e41 100644 --- a/proparse/src/test/resources/data/preprocessor/preprocessor02.p +++ b/proparse/src/test/resources/data/preprocessor/preprocessor02.p @@ -22,6 +22,7 @@ { preprocessor/preprocessor02-03.i } {&_proparse_ prolint-nowarn(messagekeywordmatch)} -{&_proparse_ prolint-nowarn(messagekeywordmatch)} -{&_proparse_ prolint-nowarn(messagekeywordmatch)} + {&_proparse_ prolint-nowarn(messagekeywordmatch) } +{&_proparse_ prolint-nowarn(messagekeywordmatch) +} { preprocessor/preprocessor02-03.i } diff --git a/proparse/src/test/resources/data/preprocessor/preprocessor15.p b/proparse/src/test/resources/data/preprocessor/preprocessor15.p index 77e3a8b57..fe926c50b 100644 --- a/proparse/src/test/resources/data/preprocessor/preprocessor15.p +++ b/proparse/src/test/resources/data/preprocessor/preprocessor15.p @@ -1,5 +1,5 @@ // Variable FOO is expanded by preprocessor, and will result in OutOfRange problem with CPD // Expansion should be reverted for CPD. -&scoped-define FOO LongLongName -MESSAGE "{&FOO}" VIEW-AS +&scoped-define FOO LongLongLongLongLongLongLongLongName +MESSAGE "{&FOO }" VIEW-AS ALERT-BOX. diff --git a/proparse/src/test/resources/data/preprocessor/preprocessor18.p b/proparse/src/test/resources/data/preprocessor/preprocessor18.p index d6d6215e6..c127c1d3b 100644 --- a/proparse/src/test/resources/data/preprocessor/preprocessor18.p +++ b/proparse/src/test/resources/data/preprocessor/preprocessor18.p @@ -1,3 +1,3 @@ { preprocessor/preprocessor18.i ¶m1= "value1" ¶m2 = - "value2" }. + "value2" }.