@@ -643,21 +643,112 @@ module TestPostProcessing {
643643
644644 module Make<InlineExpectationsTestSig Input, InputSig<Input> Input2> {
645645 private import InlineExpectationsTest as InlineExpectationsTest
646- private import InlineExpectationsTest::Make<Input>
646+
647+ bindingset[loc]
648+ private predicate parseLocationString(
649+ string loc, string relativePath, int sl, int sc, int el, int ec
650+ ) {
651+ relativePath = loc.splitAt(":", 0) and
652+ sl = loc.splitAt(":", 1).toInt() and
653+ sc = loc.splitAt(":", 2).toInt() and
654+ el = loc.splitAt(":", 3).toInt() and
655+ ec = loc.splitAt(":", 4).toInt()
656+ }
657+
658+ pragma[nomagic]
659+ private string getRelativePathTo(string absolutePath) {
660+ exists(Input::Location loc |
661+ loc.hasLocationInfo(absolutePath, _, _, _, _) and
662+ parseLocationString(Input2::getRelativeUrl(loc), result, _, _, _, _)
663+ )
664+ }
665+
666+ private newtype TTestLocation =
667+ MkInputLocation(Input::Location loc) or
668+ MkResultLocation(string relativePath, int sl, int sc, int el, int ec) {
669+ exists(string data |
670+ queryResults(_, _, _, data) and
671+ parseLocationString(data, relativePath, sl, sc, el, ec) and
672+ not Input2::getRelativeUrl(_) = data // avoid duplicate locations
673+ )
674+ }
675+
676+ /**
677+ * A location that is either an `Input::Location` or a location from an alert.
678+ *
679+ * We use this location type to support queries that select a location that does not correspond
680+ * to an instance of `Input::Location`.
681+ */
682+ abstract private class TestLocationImpl extends TTestLocation {
683+ string getAbsoluteFile() { this.hasLocationInfo(result, _, _, _, _) }
684+
685+ int getStartLine() { this.hasLocationInfo(_, result, _, _, _) }
686+
687+ int getStartColumn() { this.hasLocationInfo(_, _, result, _, _) }
688+
689+ int getEndLine() { this.hasLocationInfo(_, _, _, result, _) }
690+
691+ int getEndColumn() { this.hasLocationInfo(_, _, _, _, result) }
692+
693+ abstract string getRelativeUrl();
694+
695+ final string toString() { result = this.getRelativeUrl() }
696+
697+ abstract predicate hasLocationInfo(string file, int sl, int sc, int el, int ec);
698+ }
699+
700+ private class LocationFromResult extends TestLocationImpl, MkResultLocation {
701+ override string getRelativeUrl() {
702+ exists(string file, int sl, int sc, int el, int ec |
703+ this = MkResultLocation(file, sl, sc, el, ec) and
704+ result = file + ":" + sl + ":" + sc + ":" + el + ":" + ec
705+ )
706+ }
707+
708+ override predicate hasLocationInfo(string file, int sl, int sc, int el, int ec) {
709+ this = MkResultLocation(getRelativePathTo(file), sl, sc, el, ec)
710+ }
711+ }
712+
713+ private class LocationFromInput extends TestLocationImpl, MkInputLocation {
714+ private Input::Location loc;
715+
716+ LocationFromInput() { this = MkInputLocation(loc) }
717+
718+ override string getRelativeUrl() { result = Input2::getRelativeUrl(loc) }
719+
720+ override predicate hasLocationInfo(string file, int sl, int sc, int el, int ec) {
721+ loc.hasLocationInfo(file, sl, sc, el, ec)
722+ }
723+ }
724+
725+ final class TestLocation = TestLocationImpl;
726+
727+ module TestImpl2 implements InlineExpectationsTestSig {
728+ final class Location = TestLocation;
729+
730+ final private class ExpectationCommentFinal = Input::ExpectationComment;
731+
732+ class ExpectationComment extends ExpectationCommentFinal {
733+ Location getLocation() { result = MkInputLocation(super.getLocation()) }
734+ }
735+ }
736+
737+ private import InlineExpectationsTest::Make<TestImpl2>
647738
648739 /** Holds if the given locations refer to the same lines, but possibly with different column numbers. */
649740 bindingset[loc1, loc2]
650741 pragma[inline_late]
651- private predicate sameLineInfo(Input::Location loc1, Input::Location loc2) {
742+ private predicate sameLineInfo(TestLocation loc1, TestLocation loc2) {
652743 exists(string file, int line1, int line2 |
653744 loc1.hasLocationInfo(file, line1, _, line2, _) and
654745 loc2.hasLocationInfo(file, line1, _, line2, _)
655746 )
656747 }
657748
658749 pragma[nomagic]
659- private predicate mainQueryResult(int row, int column, Input::Location loc) {
660- queryResults(mainResultSet(), row, column, Input2:: getRelativeUrl(loc ))
750+ private predicate mainQueryResult(int row, int column, TestLocation loc) {
751+ queryResults(mainResultSet(), row, column, loc. getRelativeUrl())
661752 }
662753
663754 /**
@@ -668,7 +759,7 @@ module TestPostProcessing {
668759 */
669760 private string getSourceTag(int row) {
670761 getQueryKind() = "path-problem" and
671- exists(Input::Location sourceLoc, Input::Location selectLoc |
762+ exists(TestLocation sourceLoc, TestLocation selectLoc |
672763 mainQueryResult(row, 0, selectLoc) and
673764 mainQueryResult(row, 2, sourceLoc) and
674765 if sameLineInfo(selectLoc, sourceLoc) then result = "Alert" else result = "Source"
@@ -733,7 +824,7 @@ module TestPostProcessing {
733824 }
734825
735826 additional predicate hasPathProblemSource(
736- int row, Input::Location location, string element, string tag, string value
827+ int row, TestLocation location, string element, string tag, string value
737828 ) {
738829 getQueryKind() = "path-problem" and
739830 mainQueryResult(row, 2, location) and
@@ -742,7 +833,7 @@ module TestPostProcessing {
742833 value = ""
743834 }
744835
745- predicate hasActualResult(Input::Location location, string element, string tag, string value) {
836+ predicate hasActualResult(TestLocation location, string element, string tag, string value) {
746837 hasPathProblemSource(_, location, element, tag, value)
747838 }
748839 }
@@ -770,15 +861,15 @@ module TestPostProcessing {
770861 private predicate hasPathProblemSource = PathProblemSourceTestInput::hasPathProblemSource/5;
771862
772863 private predicate hasPathProblemSink(
773- int row, Input::Location location, string element, string tag
864+ int row, TestLocation location, string element, string tag
774865 ) {
775866 getQueryKind() = "path-problem" and
776867 mainQueryResult(row, 4, location) and
777868 queryResults(mainResultSet(), row, 5, element) and
778869 tag = getSinkTag(row)
779870 }
780871
781- private predicate hasAlert(int row, Input::Location location, string element, string tag) {
872+ private predicate hasAlert(int row, TestLocation location, string element, string tag) {
782873 getQueryKind() = ["problem", "path-problem"] and
783874 mainQueryResult(row, 0, location) and
784875 queryResults(mainResultSet(), row, 2, element) and
@@ -793,15 +884,15 @@ module TestPostProcessing {
793884 * present).
794885 */
795886 private string getValue(int row) {
796- exists(Input::Location location, string element, string tag, string val |
887+ exists(TestLocation location, string element, string tag, string val |
797888 hasPathProblemSource(row, location, element, tag, val) and
798889 result =
799890 PathProblemSourceTest::getAMatchingExpectation(location, element, tag, val, false)
800891 .getValue()
801892 )
802893 }
803894
804- predicate hasActualResult(Input::Location location, string element, string tag, string value) {
895+ predicate hasActualResult(TestLocation location, string element, string tag, string value) {
805896 exists(int row |
806897 hasPathProblemSource(row, location, element, tag, _)
807898 or
@@ -840,7 +931,7 @@ module TestPostProcessing {
840931 rankedTestFailures(row, f) and
841932 f = MkTestFailure(fl, message)
842933 |
843- column = 0 and data = Input2::getRelativeUrl( fl.getLocation())
934+ column = 0 and data = fl.getLocation().getRelativeUrl( )
844935 or
845936 column = 1 and data = fl.toString()
846937 or
0 commit comments