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

miksilo.modularLanguages.deltas.javac.classes.skeleton.JavaClassDelta.scala Maven / Gradle / Ivy

The newest version!
package miksilo.modularLanguages.deltas.javac.classes.skeleton

import miksilo.modularLanguages.core.bigrammar.BiGrammar
import miksilo.modularLanguages.core.bigrammar.grammars.BiChoice
import miksilo.modularLanguages.core.deltas._
import miksilo.modularLanguages.core.deltas.grammars.{BodyGrammar, LanguageGrammars}
import miksilo.modularLanguages.core.deltas.path.{NodeChildPath, NodePath}
import miksilo.editorParser.document.BlankLine
import miksilo.modularLanguages.core.node._
import miksilo.languageServer.core.language.{Compilation, CompilationField, Language}
import miksilo.languageServer.core.smarts.ConstraintBuilder
import miksilo.languageServer.core.smarts.objects.{Declaration, NamedDeclaration}
import miksilo.languageServer.core.smarts.scopes.objects.{Scope, ScopeVariable}
import miksilo.languageServer.core.smarts.types.DeclarationHasType
import miksilo.languageServer.core.smarts.types.objects.TypeFromDeclaration
import miksilo.modularLanguages.deltas.ConstraintSkeleton
import miksilo.modularLanguages.deltas.bytecode.types.{ArrayTypeDelta, QualifiedObjectTypeDelta, TypeSkeleton, UnqualifiedObjectTypeDelta}
import miksilo.modularLanguages.deltas.classes.{ClassDelta, HasConstraintsDelta}
import miksilo.modularLanguages.deltas.classes.ClassDelta.{ClassImports, ClassPackage, ClassParent, JavaClass, Members, Shape}
import miksilo.modularLanguages.deltas.javac.classes.{ClassCompiler, FieldDeclarationDelta}
import miksilo.modularLanguages.deltas.method.MethodDelta
import miksilo.modularLanguages.deltas.statement.BlockDelta

import scala.collection.mutable

object JavaClassDelta extends DeltaWithGrammar with Delta
  with HasDeclarationDelta with HasConstraintsDelta {

  import miksilo.modularLanguages.deltas.HasNameDelta._

  override def shape: NodeShape = ClassDelta.Shape

  override def description: String = "Defines a skeleton for the Java class."

  def getFields[T <: NodeLike](javaClass: JavaClass[T]): Seq[T] = {
    javaClass.members.filter(member => member.shape == Shape)
  }

  @scala.annotation.tailrec
  def fullyQualify(_type: NodePath, classCompiler: ClassCompiler): Unit =  _type.shape match {
    case ArrayTypeDelta.Shape => fullyQualify(ArrayTypeDelta.getElementType(_type), classCompiler)
    case UnqualifiedObjectTypeDelta.Shape =>
        val newName = classCompiler.fullyQualify(UnqualifiedObjectTypeDelta.getName(_type))
      _type.asInstanceOf[NodeChildPath].replaceWith(QualifiedObjectTypeDelta.neww(newName))
    case _ =>
  }

  def getClassCompiler(compilation: Compilation): ClassCompiler = state(compilation).classCompiler

  def getQualifiedClassName[T <: NodeLike](javaClass: JavaClass[T]): QualifiedClassName = {
    QualifiedClassName(javaClass._package ++ Seq(javaClass.name))
  }

  override def dependencies: Set[Contract] = Set(BlockDelta, MethodDelta, FieldDeclarationDelta)

  override def transformGrammars(grammars: LanguageGrammars, language: Language): Unit = {
    import grammars._

    val classMember: BiGrammar = find(MethodDelta.Shape) | find(FieldDeclarationDelta.Shape)
    val importGrammar = create(ImportGrammar)
    val importsGrammar: BiGrammar = importGrammar.manyVertical as ClassImports
    val packageGrammar = new BiChoice(keywordGrammar("package") ~~>
      identifier.someSeparated(".") ~< ";", value(Seq.empty), true) as ClassPackage
    val classParentGrammar = ("extends" ~~> identifier).option
    val nameGrammar: BiGrammar = "class" ~~> find(Name)
    val membersGrammar = "{" % (classMember.manySeparatedVertical(BlankLine) as Members).indent(BlockDelta.indentAmount) % "}"
    val nameAndParent: BiGrammar = nameGrammar ~~ classParentGrammar.as(ClassParent)
    val classGrammar = packageGrammar % importsGrammar % nameAndParent % membersGrammar asLabelledNode Shape
    find(BodyGrammar).inner = classGrammar
  }


  object ImportGrammar extends GrammarKey

  def neww(_package: Seq[String], name: String, members: Seq[Node] = Seq(), imports: List[Node] = List(), mbParent: Option[String] = None) =
    new Node(Shape,
    Members -> members,
    ClassPackage -> _package,
    Name -> name,
    ClassImports -> imports,
    ClassParent -> mbParent)

  val importToClassMap = new ShapeProperty[(Compilation, Node) => Map[String, QualifiedClassName]]

  val state = new CompilationField[State](_ => new State())
  class State {
    var classCompiler: ClassCompiler = _
    val javaCompiler: JavaCompiler = new JavaCompiler()
    var packageScopes: mutable.Map[String, Scope] = new mutable.HashMap
  }

  object ClassGrammar

  override def collectConstraints(compilation: Compilation, builder: ConstraintBuilder, path: NodePath, defaultPackageScope: Scope): Unit = {
    getClassScope(compilation, builder, path, defaultPackageScope)
  }

  def getClassScope(compilation: Compilation, builder: ConstraintBuilder, path: NodePath, defaultPackageScope: Scope): ScopeVariable = {
    val clazz: JavaClass[NodePath] = path
    val clazzDeclaration = getDeclaration(compilation, builder, clazz.node, defaultPackageScope)
    val classScope = builder.getDeclaredScope(clazzDeclaration)
    for (_import <- clazz.imports)
      ConstraintSkeleton.constraints(compilation, builder, _import, classScope)

    val members = clazz.members

    members.foreach(member =>
      ConstraintSkeleton.constraints(compilation, builder, member, classScope))

    classScope
  }

  val staticDeclaration = new TypedNodeField[NamedDeclaration]("staticDeclaration")
  override def getDeclaration(compilation: Compilation, builder: ConstraintBuilder, path: NodePath, defaultPackageScope: Scope): Declaration = {
    val clazz: JavaClass[NodePath] = path

    val packageScope = if (clazz._package.isEmpty) {
      defaultPackageScope
    } else {
      val packageParts = clazz.node._package.toList
      val fullPackage: String = packageParts.reduce[String]((a, b) => a + "." + b)
      state(compilation).packageScopes.getOrElseUpdate(fullPackage, {
        val packageDeclaration = builder.declare(fullPackage, defaultPackageScope, path)
        builder.declareScope(packageDeclaration, defaultPackageScope, fullPackage)
      })
    }

    //TODO here there should be an instance, a static, and a lexical scope.
    val clazzDeclaration = builder.declare(clazz.name, packageScope, path.getField(Name))
    val clazzType = TypeFromDeclaration(clazzDeclaration)
    builder.add(DeclarationHasType(clazzDeclaration, clazzType))
    builder.assignSubType(TypeSkeleton.typeKind, clazzType)

    val classScope = builder.declareScope(clazzDeclaration, packageScope, clazz.name)
    staticDeclaration(path) = clazzDeclaration

    val members = clazz.members
    members.foreach(member => ConstraintSkeleton.hasDeclarations(compilation, member.shape).
      getDeclaration(compilation, builder, member, classScope))

    clazzDeclaration
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy