All Downloads are FREE. Search and download functionalities are using the official Maven repository.

miksilo.modularLanguages.deltas.solidity.MultiFileDelta.scala Maven / Gradle / Ivy

The newest version!
package miksilo.modularLanguages.deltas.solidity

import miksilo.modularLanguages.core.deltas.path.{NodePath, PathRoot}
import miksilo.modularLanguages.core.deltas.{DeltaWithPhase, ShapeProperty}
import miksilo.languageServer.core.language.{Compilation, CompilationCache}
import miksilo.modularLanguages.core.node._
import miksilo.languageServer.core.smarts.ConstraintBuilder
import miksilo.languageServer.core.smarts.scopes.objects.Scope
import miksilo.modularLanguages.deltas.ConstraintSkeleton
import miksilo.modularLanguages.deltas.classes.HasConstraintsDelta

import scala.collection.mutable

object MultiFileDelta extends DeltaWithPhase with HasConstraintsDelta {

  object Shape extends NodeShape
  object Files extends NodeField

  override def transformProgram(program: Node, compilation: Compilation): Unit = {
    val phases = compilation.language.compilerPhases.takeWhile(p => p.key != this)

    def compileFile(fileReference: String): Node = {
      val fileCompilation = new Compilation(new CompilationCache(compilation.language, compilation.fileSystem), Some(fileReference))
      for(phase <- phases) {
        phase.action(fileCompilation)
      }
      fileCompilation.program.asInstanceOf[PathRoot].current // TODO correctly handle the diagnostics from this other file. Move them to the other compilation?
    }

    var fileQueue = List[Node](program)
    val visitedFiles = new mutable.HashSet[String]()
    var files = List.empty[Node]
    visitedFiles.add(compilation.rootFile.get)
    while(fileQueue.nonEmpty) {
      val file = fileQueue.head
      files ::= file
      fileQueue = fileQueue.tail

      val references = getFileReferencesFromFile(compilation, file)
      for(reference  <- references) {
        if (visitedFiles.add(reference)) {
          fileQueue ::= compileFile(reference)
        }
      }
    }

    compilation.program = PathRoot(Shape.create(Files -> files))
  }

  trait HasFileReferences {
    def getReferences(node: Node): Seq[String]
  }
  val getFile = new ShapeProperty[HasFileReferences]

  def getFileReferencesFromFile(compilation: Compilation, file: Node): Seq[String] = {
    val fileMembers = file(FileWithMembersDelta.Members).asInstanceOf[Seq[Node]]
    fileMembers.flatMap(member =>
      getFile.get(compilation, member.shape).map(f => f.getReferences(member)).getOrElse(Seq.empty))
  }

  override def description = "Enables compiling multiple files"

  override def dependencies = Set.empty

  override def shape = Shape

  override def collectConstraints(compilation: Compilation, builder: ConstraintBuilder, path: NodePath, parentScope: Scope): Unit = {
    path(Files).asInstanceOf[Seq[NodePath]].foreach(file =>
      ConstraintSkeleton.constraints(compilation, builder, file, parentScope))
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy