-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Saem nimsuggest re-enable tests #16401
Conversation
Notes:
ToDo:
|
Type of feedback I'm especially interested in:
|
nimsuggest/tests/tdot4.nim
Outdated
$nimsuggest --tester --maxresults:2 $file | ||
>sug $1 | ||
sug;;skProc;;tdot4.main;;proc (inp: string): string;;$file;;10;;5;;"";;100;;None | ||
sug;;skProc;;strutils.replace;;proc (s: string, sub: string, by: string): string{.noSideEffect, gcsafe, locks: 0.};;$lib/pure/strutils.nim;;1506;;5;;"Replaces `sub` in `s` by the string `by`.";;100;;None | ||
sug;;skFunc;;strutils.replace;;proc (s: string, sub: string, by: string): string{.noSideEffect, gcsafe, locks: 0.};;*/lib/pure/strutils.nim;;*;;5;;"Replaces `sub` in `s` by the string `by`.*";;100;;None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add dedicated module(s) only imported by nimsuggest tests:
nimsuggest/tests/mimported.nim
otherwise we'll end up with nimsuggest tests always failing everytime a change is made to those modules in stdlib.
(as you've experienced in your PR)
nimsuggest tests should only rely on its own support files nimsuggest/tests/m*.nim
If for some reason we really want to try nimsuggest on a real codebase (eg compiler/nim.nim), then at least the test should be made more robust to code changes, using for example:
let (outp, exitCode) = execShellCmdEx("nimsuggest --tester ... compiler/nim.nim")
doAssert exitCode == 0
doAssert "somethingExpected" in outp # etc, makes it more robust to line changes
but I'm not sure that's needed, we can just ensure nimsuggest/tests/mimported.nim
is comprehensive enough to add every pattern that needs testing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, thanks for the detailed feedback, @timotheecour.
I was wondering about how to isolate for those and my head jumped to using metamorphic testing, but it's likely far simpler to do it this wya. The only issue is that I believe no matter what system.nim
will always get in there. That might also be a good thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, should dep_v*.nim
become mdep_v*.nim
-- maybe not in this PR but eventually?
I tried looking up the convention, I do remember reading about m*
prefix, but I can't remember the precise convention and I'm struggling to find it again. :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, should dep_v*.nim become mdep_v*.nim
sure, noone will blame you if you do it in this PR :)
I can't remember the precise convention and I'm struggling to find it again. :(
https://nim-lang.github.io/Nim/contributing.html
Each test has its own file. All test files are prefixed with t. If you want to create a file for import into another test only, use the prefix m.
(slightly different context but same spirit)
no matter what system.nim will always get in there.
from system import nil
as a 1st statement is an option.
from system import nil
# or:
from system import int, string ...
another option is filtering out "flaky things" that include line numbers from system.nim via execShellCmdEx
based tests as shown above (see trunner.nim which relies on this pattern)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Things thus far:
deps_v*.nim
aremdeps_v*.nim
- this also stopped them from being compiled needlessly and executables being left behind
- starting to create
m*.nim
files to isolate tests, tests are faster, more stable, and scenarios more precise- need to finish moving the rest over
m*.nim
files might grow a fair bit, hopefully it's not a huge deal
from system import ...
is a slick trick, for some reason it didn't occur to me that it would work with system 😅
Thanks again for your support -- it's really welcoming.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're welcome: )
from system import ... is a slick trick, for some reason it didn't occur to me that it would work with system 😅
PR welcome to document it in https://nim-lang.github.io/Nim/system.html ; searching for from system
in there returns nothing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, at least for nimsuggest this no longer works, I'm suspecting it was introduced as part of #15935.
Now what happens is that I get a whole lot of system.* suggestions immediatelly following the mstrutils.replace one. I haven't understood the IC stuff well enough to know what exactly is happening and more importantly whether this is in fact invalid.
As an aside I was poking as the VS Code extension to see if I could improve the integration with nimsuggest and this might also explain the increase in crashes. I'll have a further look tomorrow to see if I can suss out what's happening.
Output from the test failure -- I had tester.nim output more than 200 characters:
==== STDIN ======================================
Test failed: /home/saem/Development/nim/Nim/nimsuggest/tests/tdot4.nim
Expected: *mstrutils.nim 10 5 "this is a test version of strutils.replace, it simply returns `by`" 100 None
sug skFunc mstrutils.rereplace proc (s: string, sub: string, by: string): string{.noSideEffect, gcsafe,
But got: /home/saem/Development/nim/Nim/nimsuggest/tests/mstrutils.nim 5 5 "this is a test version of strutils.replace, it simply returns `by`" 100 None
sug skProc system.add proc (x: var string, y: string){.noSideEffect.} /home/saem/Development/nim/Nim/lib/system.nim 1026 5 "Concatenates `x` and `y` in place.\x0A\x0A.. code-block:: Nim\x0A var tmp = \"\"\x0A tmp.add(\"ab\")\x0A tmp.add(\"cd\")\x0A assert(tmp == \"abcd\")" 100 None
sug skProc system.len proc (x: string): int{.noSideEffect.} /home/saem/Development/nim/Nim/lib/system.nim 697 5 "Returns the length of a string.\x0A\x0A.. code-block:: Nim\x0A var str = \"Hello world!\"\x0A echo len(str) # => 12" 100 None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will address this in a future PR after I learn some more about what should happen.
nimsuggest/tests/tsug_regression.nim
Outdated
# Open Questions: | ||
# * Why did hasKey sort above all? | ||
# * Why did getOrDefault drop off? | ||
# * Why does a deprecated procedures like `add` rank high? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did hasKey sort above all?
Why does a deprecated procedures likeadd
rank high?
see implementation:
proc suggestEverything(c: PContext, n, f: PNode, outputs: var Suggestions) =
# do not produce too many symbols:
for (it, scopeN, isLocal) in allSyms(c):
var pm: PrefixMatch
if filterSym(it, f, pm):
outputs.add(symToSuggest(c.config, it, isLocal = isLocal, ideSug, n.info, 0, pm,
c.inTypeContext > 0, scopeN))
PR welcome to improve it using heuristics you suggest:
first, generate list of all acceptable candidates and add them to a priority queue, using same approach as what I'm doing in #16067; the priority in the queue can depend on scope (as done in that PR) plus heuristics (eg deprecated ranks lower, as you suggest)
then do walk the priority queue to get results in sorted order. Alternatively, using seq + sort instead of a priority queue is ok too, that's not the main point
Why did getOrDefault drop off?
no idea, I'm curious too; please instrument code (with echo, debug(n)
from astalgo + friends) to figure out why getOrDefault
is filtered out: does filterSym
filter it out, or is it not even yieled inside suggestEverything
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out suggestEverything
is called much of the time, but not all the time. In this particular case the code ends up in sugExpr
and since we have a nkDotExpr
, it takes the suggestFieldAccess
path and ends up in suggestObject
and suggestOperations
.
Any how, getOrDefault
do in fact show up, just further down the list. While I was poking about, I found cmpSuggestions
which compares Suggest
based on various factors, one of which is quality
(Range[0..100]
). I think I should either:
- have
Suggest
note whether something is deprecated and factor it into the comparator directly - have quality by way of the
getQuality
proc lower the quality rating
I'm not a fan of adding more state, but the former is most appealing as it means quality remains a sort of measure of relevance/closeness, while deprecation feels more like a tie breaker akin to boosting. NB. I'm borrowing terminology from fulltext indexing/search engines such as Elasticsearch when I say relevance and boosting.
Whatever the change, I'm inclined to make that in a follow-up PR, want to keep this focused on tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't care much how you implement it, but I completely agree that deprecated symbols should either not be suggested at all or be of low priority.
6c4f384
to
adb069d
Compare
I would like to have the frontend properly tested as that's the part users will interact with. To speed things up we can just run tests in parallel ( |
Can we have test helper modules moved into a subfolder? |
nimsuggest/tests/twithin_macro.nim
Outdated
* from the errors that's either broken or not the way it works | ||
|
||
Open Questions: | ||
* how does nimsuggest transform the AST for suggestions or does it even? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK, nimsuggest simply hooks into the compiler sem
pass, so it does whatever the compiler would do when compiling the program. To get suggestions, nimsuggest have hook points in various places in the sem
pass, then wait until sem
process the AST node where the cursor is at, then access the symbol table of that scope to figure out what tokens are available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a minor mental breakthrough when I saw the sem pass setup in nimsuggest. The question I wrote was without that nuance, but it's still relevant I think. Even though nimsuggest isn't doing it directly, templates, macros, etc... are all being evaluated, which means lots of computation & state change going on.
At the time I wrote the question and even now, my mind keeps coming back to:
- semantic analysis of any nim code thrown at nimsuggest need to be forgiving
- additionally any compile time execution needs to also be forgiving (templates, macros, ...)
- state (expanded code, computed values, etc...) are going to have interesting impact on analysis and caching
What I'm trying to roughly point at is the above sounds like fertile ground for bugs unless and complexity in terms of usefully (correctly?) carrying out forgiving analysis and if I don't understand those bits better the chance of fixing a test like twithin_macro.nim seem rather slim. :/
Presently, the question could be refined to perhaps, "How does the semantic analysis that nimsuggest carry out via the sem pass transform the AST for generating suggestions, and how does evaluation of compile time code impact things, especially when carrying around or mutating state, carrying out an unbounded computation, employing IO, or allocating memory?". It might lose something in specificity.
IIRC, I've seen bugs like the following:
- nimsuggest goes to 100% and sits there
- unbounded computation or excessively hitting slow IO path because results weren't cached?
- nimsuggest kept groing memory because of static
- haven't read the fix yet so not sure what to make of it just yet
- lack of idempotency, I've called the same call twice in a row and I get different results
- reminds me of Haxe where certain macros must be authored with compilation cache awareness or :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You know the answer to your questions already. There is some logic that prevents IO from being done in the VM for nimsuggest but all the other problems are there. However, ignoring the fact that plenty of code wasn't written with these restrictions in mind (hence bugs), the restrictions are not that hard to follow: There can be error types and nodes in the AST and processing should ignore them and continue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Araq thanks for confirming -- also provides some hints for potentially quick PRs.
I'm reading through notes and open questions and cleaning them up accordingly.
Outside scope of PR. |
adb069d
to
2fd2151
Compare
Done |
ddcd86d
to
90eac05
Compare
I'm inclined to squash all these into one commit -- just want to get confirmation from a reviewer before I do that. There isn't a particularly meaningful separation to be made as I played with a few different approaches. |
that's fine (note that we now automatically enforce squashing before merging PR's anyways). |
A number of nimsuggest tests were disabled for various reasons, sometimes due to brittleness. These tests have been fixed where needed and most have are now enabled -- details below. The updates are meant to provide better regression coverage for future nimsuggest improvements. To avoid brittleness some tests were refactored. Impact: * test coverage has now increased * faster execution of the test suite * tests are less likely to break due to stdlib changes Re-enabled Test & Test Description: * `tchk1.nim`: check (chk) via nimsuggest works at end of file * `tdot4.nim`: prioritize already used completion * `tinclude.nim`: definition lookup (def) with includes * `tstrutils.nim` -> `tdef2.nim`: test template definition lookup (def) * `tsug_regression.nim`: regression test for [nimsuggest nim-lang#52](nim-lang/nimsuggest#52) * `ttemplate_highlight.nim`: per the file name * `twithin_macro_prefix.nim`: suggest within a macro with a prefix Tests Not Re-Enabled: * `twithin_macro.nim` still disabled as it doesn't provide a good test signal * EPC highlight tests remain disabled -- requires out of scope tester changes Additional Notes: * todos added in comments for follow-up work
fc0ddde
to
47e906b
Compare
Done -- rebased on top of devel and squashed to a single commit. |
A number of nimsuggest tests were disabled for various reasons, sometimes due to brittleness. These tests have been fixed where needed and most have are now enabled -- details below. The updates are meant to provide better regression coverage for future nimsuggest improvements. To avoid brittleness some tests were refactored. Impact: * test coverage has now increased * faster execution of the test suite * tests are less likely to break due to stdlib changes Re-enabled Test & Test Description: * `tchk1.nim`: check (chk) via nimsuggest works at end of file * `tdot4.nim`: prioritize already used completion * `tinclude.nim`: definition lookup (def) with includes * `tstrutils.nim` -> `tdef2.nim`: test template definition lookup (def) * `tsug_regression.nim`: regression test for [nimsuggest nim-lang#52](nim-lang/nimsuggest#52) * `ttemplate_highlight.nim`: per the file name * `twithin_macro_prefix.nim`: suggest within a macro with a prefix Tests Not Re-Enabled: * `twithin_macro.nim` still disabled as it doesn't provide a good test signal * EPC highlight tests remain disabled -- requires out of scope tester changes Additional Notes: * todos added in comments for follow-up work
@saem I'm having a hard time running tests locally:
also note that |
A number of nimsuggest tests were disabled for various reasons, sometimes due to brittleness. These tests have been fixed where needed and most have are now enabled -- details below. The updates are meant to provide better regression coverage for future nimsuggest improvements. To avoid brittleness some tests were refactored. Impact: * test coverage has now increased * faster execution of the test suite * tests are less likely to break due to stdlib changes Re-enabled Test & Test Description: * `tchk1.nim`: check (chk) via nimsuggest works at end of file * `tdot4.nim`: prioritize already used completion * `tinclude.nim`: definition lookup (def) with includes * `tstrutils.nim` -> `tdef2.nim`: test template definition lookup (def) * `tsug_regression.nim`: regression test for [nimsuggest nim-lang#52](nim-lang/nimsuggest#52) * `ttemplate_highlight.nim`: per the file name * `twithin_macro_prefix.nim`: suggest within a macro with a prefix Tests Not Re-Enabled: * `twithin_macro.nim` still disabled as it doesn't provide a good test signal * EPC highlight tests remain disabled -- requires out of scope tester changes Additional Notes: * todos added in comments for follow-up work
Bolster test suite in order to serve catch regressions:
tchk1.nim
: check (chk) via nimsuggest works at end of filetdot4.nim
: prioritize already used completiontinclude.nim
: definition lookup (def) with includeststrutils.nim
->tdef2.nim
: test template definition lookup (def)tsug_regression.nim
: regression test for nimsuggest #52ttemplate_highlight.nim
: per the file nametwithin_macro_prefix.nim
: suggest within a macro with a prefixtwithin_macro.nim
was not enabled as it doesn't seem to provide a good signal