I am rather new to Semgrep but I have been loving it so far. I found what I believe to be a problem after taking the rather-excellent tutorial. My problem is related to imports which seems relevant to #2234 and possibly also #285?
The bug report submission option from the live editor auto-generated this link: https://semgrep.dev/s/0Qgq
Pattern:
import $IMPORTS from $FILE;
I would have expected it to match all of the following lines and not just the last one:
// No matches
import { Panda } from './file';
import { Panda, Bamboo, Curry } from './file';
// Matches
import Panda from './file';
In fact, augmenting the pattern with curly braces also does not work as I would expect it to work.
import { $IMPORTS } from $FILE;
import {..., $IMPORTS, ...} from $FILE;
Please let me know if I've done something wrong or if I can provide additional information. Thanks so much for all the awesome work and let me know if I can provide any useful test code or use cases.
Thanks,
+Jonathan
Hi @yonkeltron, thanks for such a great writeup and taking the time to link previous issues, and glad you've found Semgrep useful! Our Typescript support is in beta (https://semgrep.dev/docs/status) so filing issues like this is extremely helpful for us to promote it to GA status. To help the team triage this issue, can you share the relative priority for you? P2: low priority; P1: annoying but not a blocker; P0: blocking your further usage of Semgrep.
Yes right now P0. This is blocking my use of Semgrep as we am looking to employ Semgrep on a research project which, likely, specifically deals with imports. Happy to share more about the use case if needed but I'll need to look at other options for analyzing TypeScript code absent this feature. Obviously I could still use Semgrep for this sort of thing in other languages like, say, Python.
Does this make sense? How can I contribute further to the discussion and process? Perhaps I can provide some ideal patterns or something which I would want to be able to match?
Thanks @yonkeltron for sharing that -- I've added a priority label so we'll see what @aryx or @mjambon think soon.
If you'd like to push the process ahead today further, feel free to comment with more ideal patterns + expectations on what they would match. If you're feeling even more ambitious, you could make a PR to the typescript unit tests directory https://github.com/returntocorp/semgrep/tree/develop/semgrep-core/tests/ts, (specifically metavar_import.ts and metavar_import.sgrep) which follows a pretty simple structure for expected vs. not-expected pattern matching results. (And if you know OCaml, feel free to dig into the implementation!)
I confess that my OCaml is rather ghastly, despite having read the most excellent text of Minsky's book. I actually knew his brother once upon a time.
In any case, I will work with my team to compile some examples of precisely what we'd need.
import { Panda, Bamboo, Curry } from './file';
class Noodle {
constructor(public readonly critter: Panda) {}
feed(food: Bamboo): Curry {
return this.critter.cookMealWith(food);
}
}
rules:
- id: imports-in-general
pattern: |
import $IMPORTS from ".$FILE";
- id: import-used-as-param
pattern: |
import {..., $ID, ...} from ".$FILE";
...
$FUNC(...: $ID) ... {
...
}
- id: import-used-as-return-type
pattern: |
import {..., $ID, ...} from ".$FILE";
...
$FUNC(...): $ID {
...
}
For internal reference: typescript modules, relevant part of the generic AST.
I'm hoping to look into this by the end of the week, depending on outcome of current task.
Hey Jonathan. I got some success after a bit of trial and error. Here's what I found works:
Given the target program:
import { Bamboo, Curry } from './file';
import Panda from './file';
Semgrep will find 3 matches for the pattern import { $ID } from $FILE;:
BambooCurryPandaIt's not obvious from the live editor because of how the first two matches overlap (https://semgrep.dev/s/dK0Y).
However, without the braces in the pattern (import $ID from $FILE;), semgrep will only match Panda. I'm not sure if it matters for your use case.
Your second pattern (import-used-as-param) can be written as:
import { $ID } from "...";
...
function $FUNC($X: $ID) {
...
}
Result: https://semgrep.dev/s/ndkO
The third pattern (import-used-as-return-type) is similar:
import { $ID } from "...";
...
function $FUNC(...): $ID {
...
}
Result: https://semgrep.dev/s/EkOA
Let us know if that helps. The best advice here I think is "trial and error".
Hey thanks for this. My team and I are reviewing this and will get back to you as soon as we can assess.
Thanks,
+Jonathan
Closing for now as martin's solution seems to satisfy your need.