Language feature for scoped restrictions?

I need a way to restrict what things I am able to do in specific scopes.

For example, I need to restrict usage of the java.io or kotlin.io packages. I am developing my own frameworks for working with files, which may use those packages internally. but there is nothing stopping me from using those packages in places where I don’t want to.

One possibility is that I can write function in a common module (no access to jvm). But this seems like it accomplishes my goal only as a side effect, and won’t work in all cases.

I am looking for something vaguely like the following:

@Prohibit("java.io.*","kotlin.io.*")
annotation class RestrictedIoScope

Above, Prohibit would be a built in annotation provided by the kotlin language. It is inspired by DslMarker. RestrictedIoScope would be created by the developer. It might work something like this:

   
@RestrictedIoScope
interface MyIoContext

context(MyIoContext)
fun customIoOnly() {
    java.io.File("/a/file.txt").readText() // <- would throw a compiler error for violating the restriction
}
   

Vaguely Similar features I can think of are:

  • DslMarker
  • Opt-In Requirements
  • Multiplatform Common Modules
  • Deprecation
  • implementation dependencies in gradle (as opposed to api)

These are all features built into the kotlin language that can help a developer have some enforcement for what is used where. But none of these allow the developer to specifically prohibit certain classes or packages from being used, especially if those are from the standard libraries.

There is also the possibility of using a custom lint rule or compiler plugin, but that seems like overkill and might be too difficult.

Are there any other ways to enforce forbidding certain standard library functions that I have not thought of or considered?

You may be interested in frameworks such as archunit. Setting an intelliJ linter rule maybe even more helpful, because it will point out the problem while you code. But if you wish to allow for exceptions that may not be possible via an intelliJ rule.

As for the cost/benefit ratio, that depends on the size of your project. Namely if you only have upto 10 classes (source files), it may not be worth it (except if you wish to make it a PoC). But if you plan on a project with 20+ classes (or source files), then some architectural rules can be handy, especially if you are developing with some junior developers.

The mentioned technics are no rocket science, i.e. others already got them working, and so probably can you. Just give it a try (if it is worthwile for you).

1 Like