Is there any way to get a view on the script to be...
# scripting
o
Is there any way to get a view on the script to be compiled after it has been parsed? I am using the
beforeCompiling
block in
refineConfiguration
to do some checks in the
source.text
- but I would need comments already removed from the code snippet... I don't want to reimplement a code parser... 😞
p
I think there's a lib that can parse Kotlin to an AST or PSI, would that suffice?
I'd check how ktlint parses Kotlin, I think it uses a lib from JB
o
Yes, theoretically that would do the trick. But shouldn't such a component be included in the scripting library itself as it must contain everything to compile the script?
p
the scripting's API may just not expose the AST, and it exposes the full source code for you to work with (not sure if it's 100%, but I can imagine this)
o
What I want to know for sure is one thing: does the given script use certain Java classes or not. More concrete: I want to forbid the use of legacy Java classes like Date, Calendar, etc. Using Regex to find that is kind of impossible...
I noticed e.g. that you can break the lines when using
java.util.Date
like this
Copy code
java.   
util.
Date()
This I can still find with a multiline Regex... but...
Copy code
java. // boo!
util.
Date()
Is impossible to detect without starting to parse completely.
p
hmm, it sounds like linting. Here's a crazy idea: maybe it's possible to hook up detekt which I think now operates as a compiler plugin and could detect these? it may be an overkill, though
o
Yeah, I would also not want to do any overkill solution... 😉 It should stay as lightweight as possible, both in terms of dependencies and time to compile... I can probably live with my very rudimentary approach, it is not about fighting attackers, it is more to help users who don't know better. So, if there is still a way to reach out to the bad things, it's probably something I can ignore...
👍 1
i
[highly experimental alert] I'm right now in the process of refactoring the refinement logic for K2 scripting. The main reason is to drop the dependency on the K1 specific AST representation that is used for implementing
refineOnAnnotations
. But what I'm implementing is a more generic ability to get a full AST (based on the unresolved FIR) representation in the callback. I think this should help, provided that the refactoring will not end up being blocked by some difficulties.
👍 3
m
(eagerly awaiting K2-ness for a whole host of reasons). I do increasingly elaborate things with code like this:
Copy code
val cs = compiler.state.getCompilationState(compilerConfig)
val env = cs.environment
val project = env.project

val factory = PsiFileFactory.getInstance(project)
val lang = Language.findLanguageByID("kotlin")!!
val instance = factory.createFileFromText(lang, s)

instance.forEachDescendantOfType<PsiElement> { expression ->
    when (expression) {
        is KtCallExpression -> { 
            ...
Where
compilerConfig
is the
ScriptCompilationConfiguration
that I use with my
KJvmReplCompilerWithIdeServices
It gets you AST-like things with text ranges. It feels a bit sneaky, but it's been working for a while now.
On the one hand it's giving me a macro system in Kotlin, on the other hand it's basically what something mainstream like DataFrame is getting from its compiler plugin.