Skip to content

Implement auto-import #540

@olafurpg

Description

@olafurpg

It would be nice if completions could be used to override methods like here

2019-03-01 18 50 37

In order to implement this feature we need to first come up with a solution for inserting imports for symbols that are not in scope.

Here is a summary of different approaches that we can take:

  • Insert fully qualified names
  • Insert imports in nearest enclosing block
  • Insert imports at bottom of global import list nearest enclosing block
  • Insert imports at the correct place in the global import list

Insert fully qualified names

Before

    new SimpleFileVisitor[Path] {
      override def visitF<TAB>
    }

After

    new SimpleFileVisitor[Path] {
+      override def visitFile(file: java.nio.file.Path, attrs: java.nio.file.attributes.BasicFileAttributes): java.nio.file.FileVisitResult = super.visitFile(file, attrs)
    }

Pros:

  • simple to implement
  • low risk of producing code that doesn't compile

Cons:

  • converting fully qualified names java.nio.file.attributes.BasicFileAttributes into import + short name is time consuming and cumbersome

Insert imports in nearest enclosing block

Before

    new SimpleFileVisitor[Path] {
      override def visitF<TAB>
    }

After

+import java.nio.file.Path
+import java.nio.file.FileVisitResult
+import java.nio.file.attributes.BasicFileAttributes
    new SimpleFileVisitor[Path] {
+      override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = super.visitFile(file, attrs)
    }

Pros:

  • simple to implement
  • locally scoped imports lower risk of breaking code in different places in the source file
  • handles majority of the cumbersome work of splitting fully qualified names into imports
  • gives the user control over where to place imports and how to group them

Cons:

  • users might end up a lot of local imports that should really be global
  • moving local imports to global imports is time consuming and cumbersome

Insert imports at bottom of global import list nearest enclosing block

Before

import scala.language.higherKinds

import java.util._

import scala.collection.concurrent.TrieMap

object Main { 
    new SimpleFileVisitor[Path] {
      override def visitF<TAB>
    }
}

After

import scala.language.higherKinds

import java.util._

import scala.collection.concurrent.TrieMap
+import java.nio.file.Path
+import java.nio.file.FileVisitResult
+import java.nio.file.attributes.BasicFileAttributes

object Main { 
    new SimpleFileVisitor[Path] {
+      override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = super.visitFile(file, attrs)
    }
}

Pros:

  • simple to implement
  • handles majority of the cumbersome work of moving local imports to global imports

Cons:

  • users still need manual work to organize imports according to the codebase conventions
  • the inserted imports are not visible in the editor when completing, so users might not notice the diffs while coding.
  • higher risk that the inserted imports break code elsewhere in the source file

Insert imports at the correct place in the global import list

Before

import scala.language.higherKinds

import java.util._

import scala.collection.concurrent.TrieMap

object Main { 
    new SimpleFileVisitor[Path] {
      override def visitF<TAB>
    }
}

After

import scala.language.higherKinds

import java.util._
+import java.nio.file.Path
+import java.nio.file.FileVisitResult
+import java.nio.file.attributes.BasicFileAttributes

import scala.collection.concurrent.TrieMap


object Main { 
    new SimpleFileVisitor[Path] {
+      override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = super.visitFile(file, attrs)
    }
}

Pros:

  • fully automatic, user doesn't have to think about imports. This is how it works in IntelliJ.

Cons:

  • difficult to implement
  • needs a lot of configuration to reproduce common coding styles in the community
  • higher risk that the inserted imports break code elsewhere in the source file
  • incorrect configuration results in unwanted diffs that the user doesn't notice while coding. It's very common during code review to see contributors make unrelated diffs in the imports because they have different intellij import settings.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions