<commit_before>/*
 * Copyright 2005-2010 LAMP/EPFL
 */
// $Id$

package scala.tools.eclipse.javaelements

import java.io.{ PrintWriter, StringWriter }
import java.util.{ Map => JMap }

import org.eclipse.core.resources.IFile
import org.eclipse.jdt.core.{ IAnnotation, ICompilationUnit, IJavaElement, IMemberValuePair, Signature }
import org.eclipse.jdt.core.compiler.CharOperation
import org.eclipse.jdt.internal.core.{
  Annotation, AnnotationInfo => JDTAnnotationInfo, AnnotatableInfo, CompilationUnit => JDTCompilationUnit, ImportContainer,
  ImportContainerInfo, ImportDeclaration, ImportDeclarationElementInfo, JavaElement, JavaElementInfo, JavaModelManager,
  MemberValuePair, OpenableElementInfo, SourceRefElement }
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants
import org.eclipse.jdt.ui.JavaElementImageDescriptor

import scala.collection.Map
import scala.collection.mutable.HashMap

import scala.tools.nsc.symtab.Flags
import scala.tools.nsc.util.{ NoPosition, Position }

import scala.tools.eclipse.ScalaPresentationCompiler
import scala.tools.eclipse.util.ReflectionUtils

trait ScalaStructureBuilder { self : ScalaPresentationCompiler =>

  class StructureBuilderTraverser(scu : ScalaCompilationUnit, unitInfo : OpenableElementInfo, newElements0 : JMap[AnyRef, AnyRef], sourceLength : Int) {
    private val manager = JavaModelManager.getJavaModelManager

    type OverrideInfo = Int
    var overrideInfos : collection.mutable.Map[Symbol, OverrideInfo] = _
    def fillOverrideInfos(c : Symbol) {
      overrideInfos = new collection.mutable.HashMap[Symbol, OverrideInfo]
      val opc = new overridingPairs.Cursor(c)
      while (opc.hasNext) {
        if (!opc.overridden.isClass && opc.overriding.pos.isOpaqueRange) {
          overrideInfos += opc.overriding -> (if (opc.overridden.isDeferred) JavaElementImageDescriptor.IMPLEMENTS else JavaElementImageDescriptor.OVERRIDES)
        }
        opc.next
      }
    }

    def methodOverrideInfo(m : Symbol) = overrideInfos.getOrElse(m, 0)
    
    trait Owner {
      def parent : Owner
      def jdtOwner = this

      def element : JavaElement
      def elementInfo : JavaElementInfo
      def compilationUnitBuilder : CompilationUnitBuilder = parent.compilationUnitBuilder
      
      def isPackage = false
      def isCtor = false
      def isTemplate = false
      def template : Owner = if (parent != null) parent.template else null

      def addPackage(p : PackageDef) : Owner = this
      def addImport(i : Import) : Owner = this
      def addClass(c : ClassDef) : Owner = this
      def addModule(m : ModuleDef) : Owner = this
      def addVal(v : ValDef) : Owner = this
      def addType(t : TypeDef) : Owner = this
      def addDef(d : DefDef) : Owner = this
      def addFunction(f : Function) : Owner = this
      
      def resetImportContainer {}

      def addChild(child : JavaElement) =
        elementInfo match {
          case scalaMember : ScalaMemberElementInfo => scalaMember.addChild0(child)
          case openable : OpenableElementInfo => OpenableElementInfoUtils.addChild(openable, child)
          case _ =>
        }
      
      def modules : Map[Symbol, ScalaElementInfo] = Map.empty 
      def classes : Map[Symbol, (ScalaElement, ScalaElementInfo)] = Map.empty
      
      def complete {
        def addForwarders(classElem : ScalaElement, classElemInfo : ScalaElementInfo, module: Symbol) {
          def conflictsIn(cls: Symbol, name: Name) =
            cls.info.nonPrivateMembers.exists(_.name == name)
          
          /** List of parents shared by both class and module, so we don't add forwarders
           *  for methods defined there - bug #1804 */
          lazy val commonParents = {
            val cps = module.info.baseClasses
            val mps = module.companionClass.info.baseClasses
            cps.filter(mps contains)
          }
          /* the setter doesn't show up in members so we inspect the name */
          def conflictsInCommonParent(name: Name) =
            commonParents exists { cp => name startsWith (cp.name + "$") }
                 
          /** Should method `m' get a forwarder in the mirror class? */
          def shouldForward(m: Symbol): Boolean =
            m.isMethod &&
	    !m.isConstructor &&
	    !m.isStaticMember &&
	    !(m.owner == definitions.ObjectClass) && 
	    !(m.owner == definitions.AnyClass) &&
	    !m.hasFlag(Flags.CASE | Flags.PROTECTED | Flags.DEFERRED) &&
	    !module.isSubClass(module.companionClass) &&
	    !conflictsIn(definitions.ObjectClass, m.name) &&
	    !conflictsInCommonParent(m.name) && 
	    !conflictsIn(module.companionClass, m.name)
          
          assert(module.isModuleClass)
          
          for (m <- module.info.nonPrivateMembers; if shouldForward(m))
            addForwarder(classElem, classElemInfo, module, m)
        }

        def addForwarder(classElem: ScalaElement, classElemInfo : ScalaElementInfo, module: Symbol, d: Symbol) {
          //val moduleName = javaName(module) // + "$"
          //val className = moduleName.substring(0, moduleName.length() - 1)

          val nm = d.name
          
          val fps = for(vps <- d.tpe.paramss; vp <- vps) yield vp
          
          def paramType(sym : Symbol) = {
            val tpe = sym.tpe
            if (sym.isType || tpe != null)
              uncurry.transformInfo(sym, tpe).typeSymbol
            else {
              NoSymbol
            }
          }
          
          val paramTypes = Array(fps.map(v => Signature.createTypeSignature(mapType(paramType(v)), false)) : _*)
          val paramNames = Array(fps.map(n => nme.getterName(n.name).toString.toArray) : _*)
          
          val defElem = 
            if(d.hasFlag(Flags.ACCESSOR))
              new ScalaAccessorElement(classElem, nm.toString, paramTypes)
            else
              new ScalaDefElement(classElem, nm.toString, paramTypes, true, nm.toString, methodOverrideInfo(d))
          resolveDuplicates(defElem)
          classElemInfo.addChild0(defElem)
          
          val defElemInfo = new ScalaSourceMethodInfo
          
          defElemInfo.setArgumentNames(paramNames)
          defElemInfo.setExceptionTypeNames(new Array[Array[Char]](0))
          val tn = manager.intern(mapType(d.tpe.finalResultType.typeSymbol).toArray)
          defElemInfo.asInstanceOf[FnInfo].setReturnType(tn)
  
          val annotsPos = addAnnotations(d, defElemInfo, defElem)
  
          defElemInfo.setFlags0(ClassFileConstants.AccPublic|ClassFileConstants.AccFinal|ClassFileConstants.AccStatic)
          
          val (start, point, end) =
            d.pos match {
              case NoPosition =>
                (module.pos.point, module.pos.point, module.pos.point)
              case pos =>
                (d.pos.startOrPoint, d.pos.point, d.pos.endOrPoint)
            }
            
          val nameEnd = point+defElem.labelName.length-1
            
          defElemInfo.setNameSourceStart0(point)
          defElemInfo.setNameSourceEnd0(nameEnd)
          defElemInfo.setSourceRangeStart0(start)
          defElemInfo.setSourceRangeEnd0(end)
          
          newElements0.put(defElem, defElemInfo)
        } 
        
        for ((m, mInfo) <- modules) {
          val c = m.companionClass
          if (c != NoSymbol) {
            classes.get(c) match {
              case Some((classElem, classElemInfo)) =>
                addForwarders(classElem, classElemInfo, m.moduleClass)
              case _ =>
            }
          } else {
            val className = m.nameString
            
            val classElem = new ScalaClassElement(element, className, true)
            resolveDuplicates(classElem)
            addChild(classElem)
            
            val classElemInfo = new ScalaElementInfo
            classElemInfo.setHandle(classElem)
            classElemInfo.setFlags0(ClassFileConstants.AccSuper|ClassFileConstants.AccFinal|ClassFileConstants.AccPublic)
            classElemInfo.setSuperclassName("java.lang.Object".toArray)
            classElemInfo.setSuperInterfaceNames(null)
            classElemInfo.setNameSourceStart0(mInfo.getNameSourceStart)
            classElemInfo.setNameSourceEnd0(mInfo.getNameSourceEnd)
            classElemInfo.setSourceRangeStart0(mInfo.getDeclarationSourceStart)
            classElemInfo.setSourceRangeEnd0(mInfo.getDeclarationSourceEnd)
            
            newElements0.put(classElem, classElemInfo)
            
            addForwarders(classElem, classElemInfo, m.moduleClass)
          }
        }
      }
    }
    
    trait PackageOwner extends Owner { self =>
      override def addPackage(p : PackageDef) : Owner = {
        //println("Package defn: "+p.name+" ["+this+"]")
        
        new Builder {
          val parent = self
          val element = compilationUnitBuilder.element
          val elementInfo = compilationUnitBuilder.elementInfo
          
          override def isPackage = true
          var completed = !compilationUnitBuilder.element.isInstanceOf[JDTCompilationUnit]
          override def addChild(child : JavaElement) = {
            if (!completed) {
              completed = true
              
              val pkgElem = JavaElementFactory.createPackageDeclaration(compilationUnitBuilder.element.asInstanceOf[JDTCompilationUnit], p.symbol.fullName)
              resolveDuplicates(pkgElem)
              compilationUnitBuilder.addChild(pkgElem)

              val pkgElemInfo = JavaElementFactory.createSourceRefElementInfo
              newElements0.put(pkgElem, pkgElemInfo)
            }
            
            compilationUnitBuilder.addChild(child)
          }
        }
      }
    }
    
    trait ImportContainerOwner extends Owner { self =>
      import SourceRefElementInfoUtils._
      import ImportContainerInfoUtils._
    
      var currentImportContainer : Option[(ImportContainer, ImportContainerInfo)] = None
      
      override def resetImportContainer : Unit = currentImportContainer = None
      
      override def addImport(i : Import) : Owner = {
        //println("Import "+i)
        val prefix = i.expr.symbol.fullName
        val pos = i.pos

        def isWildcard(s: ImportSelector) : Boolean = s.name == nme.WILDCARD

        def addImport(name : String, isWildcard : Boolean) {
          val path = prefix+"."+(if(isWildcard) "*" else name)
          
          val (importContainer, importContainerInfo) = currentImportContainer match {
            case Some(ci) => ci
            case None =>
              val importContainerElem = JavaElementFactory.createImportContainer(element)
              val importContainerElemInfo = new ImportContainerInfo
                
              resolveDuplicates(importContainerElem)
              addChild(importContainerElem)
              newElements0.put(importContainerElem, importContainerElemInfo)
              
              val ci = (importContainerElem, importContainerElemInfo)
              currentImportContainer = Some(ci)
              ci
          }
          
          val importElem = JavaElementFactory.createImportDeclaration(importContainer, path, isWildcard)
          resolveDuplicates(importElem)
        
          val importElemInfo = new ImportDeclarationElementInfo
          setSourceRangeStart(importElemInfo, pos.startOrPoint)
          setSourceRangeEnd(importElemInfo, pos.endOrPoint-1)
        
          val children = getChildren(importContainerInfo)
          if (children.isEmpty)
            setChildren(importContainerInfo, Array[IJavaElement](importElem))
          else
            setChildren(importContainerInfo, children ++ Seq(importElem))
            
          newElements0.put(importElem, importElemInfo)
        }

        i.selectors.foreach(s => addImport(s.name.toString, isWildcard(s)))
        
        self
      }
    }
    
    trait ClassOwner extends Owner { self =>
      override val classes = new HashMap[Symbol, (ScalaElement, ScalaElementInfo)]
    
      override def addClass(c : ClassDef) : Owner = {
        //println("Class defn: "+c.name+" ["+this+"]")
        //println("Parents: "+c.impl.parents)
        
        val name0 = c.name.toString
        val isAnon = name0 == "$anon"
        val name = if (isAnon) "" else name0
        
        val parentTree = c.impl.parents.head
        val superclassType = parentTree.tpe
        val (superclassName, primaryType, interfaceTrees) =
          if (superclassType == null)
            (null, null, c.impl.parents)
          else if (superclassType.typeSymbol.isTrait)
            (null, superclassType.typeSymbol, c.impl.parents)
          else {
            val interfaceTrees0 = c.impl.parents.drop(1) 
            val superclassName0 = superclassType.typeSymbol.fullName
            if (superclassName0 == "java.lang.Object") {
              if (interfaceTrees0.isEmpty)
                ("java.lang.Object".toCharArray, null, interfaceTrees0)
              else
                (null, interfaceTrees0.head.tpe.typeSymbol, interfaceTrees0)
            }
            else
              (superclassName0.toCharArray, superclassType.typeSymbol, interfaceTrees0)   
          }

        val classElem =
          if(c.mods.isTrait)
            new ScalaTraitElement(element, name)
          else if (isAnon) {
            val primaryTypeString = if (primaryType != null) primaryType.name.toString else null
            new ScalaAnonymousClassElement(element, primaryTypeString)
          }
          else
            new ScalaClassElement(element, name, false)
        
        resolveDuplicates(classElem)
        addChild(classElem)
        
        val classElemInfo = new ScalaElementInfo
        classes(c.symbol) = (classElem, classElemInfo)
        
        classElemInfo.setHandle(classElem)
        val mask = ~(if (isAnon) ClassFileConstants.AccPublic else 0)
        classElemInfo.setFlags0(mapModifiers(c.mods) & mask)
        
        val annotsPos = addAnnotations(c.symbol, classElemInfo, classElem)

        classElemInfo.setSuperclassName(superclassName)
        
        val interfaceTypes = interfaceTrees.map(t => (t, t.tpe))
        val interfaceNames = interfaceTypes.map({ case (tree, tpe) => (if (tpe ne null) tpe.typeSymbol.fullName else "null-"+tree).toCharArray })
        classElemInfo.setSuperInterfaceNames(interfaceNames.toArray)
        
        val (start, end) = if (!isAnon) {
          val start0 = c.pos.point 
          (start0, start0 + name.length - 1)
        } else if (primaryType != null) {
          val start0 = parentTree.pos.point
          (start0, start0 + primaryType.name.length - 1)
        } else {
          val start0 = parentTree.pos.point
          (start0, start0 - 1)
        }
        
        classElemInfo.setNameSourceStart0(start)
        classElemInfo.setNameSourceEnd0(end)
        setSourceRange(classElemInfo, c, annotsPos)
        newElements0.put(classElem, classElemInfo)

        fillOverrideInfos(c.symbol)
        
        new Builder {
          val parent = self
          val element = classElem
          val elementInfo = classElemInfo
          
          override def isTemplate = true
          override def template = this
        }
      }
    }
    
    trait ModuleOwner extends Owner { self =>
      override val modules = new HashMap[Symbol, ScalaElementInfo]

      override def addModule(m : ModuleDef) : Owner = {
        //println("Module defn: "+m.name+" ["+this+"]")
        
        val isSynthetic = m.symbol.hasFlag(Flags.SYNTHETIC)
        val moduleElem = new ScalaModuleElement(element, m.name.toString, isSynthetic)
        resolveDuplicates(moduleElem)
        addChild(moduleElem)
        
        val moduleElemInfo = new ScalaElementInfo
        if (m.symbol.owner.isPackageClass)
          modules(m.symbol) = moduleElemInfo
        
        moduleElemInfo.setHandle(moduleElem)
        moduleElemInfo.setFlags0(mapModifiers(m.mods)|ClassFileConstants.AccFinal)
        
        val annotsPos = addAnnotations(m.symbol, moduleElemInfo, moduleElem)

        val start = m.pos.point
        val end = start+m.name.length-1
        
        moduleElemInfo.setNameSourceStart0(start)
        moduleElemInfo.setNameSourceEnd0(end)
        if (!isSynthetic)
          setSourceRange(moduleElemInfo, m, annotsPos)
        else {
          moduleElemInfo.setSourceRangeStart0(end)
          moduleElemInfo.setSourceRangeEnd0(end)
        }
        newElements0.put(moduleElem, moduleElemInfo)
        
        val parentTree = m.impl.parents.head
        val superclassType = parentTree.tpe
        val superclassName = (if (superclassType ne null) superclassType.typeSymbol.fullName else "null-"+parentTree).toCharArray
        moduleElemInfo.setSuperclassName(superclassName)
        
        val interfaceTrees = m.impl.parents.drop(1)<commit_msg>Exception on a module without a symbol. When does this happen?<commit_after>/*
 * Copyright 2005-2010 LAMP/EPFL
 */
// $Id$

package scala.tools.eclipse.javaelements

import java.io.{ PrintWriter, StringWriter }
import java.util.{ Map => JMap }

import org.eclipse.core.resources.IFile
import org.eclipse.jdt.core.{ IAnnotation, ICompilationUnit, IJavaElement, IMemberValuePair, Signature }
import org.eclipse.jdt.core.compiler.CharOperation
import org.eclipse.jdt.internal.core.{
  Annotation, AnnotationInfo => JDTAnnotationInfo, AnnotatableInfo, CompilationUnit => JDTCompilationUnit, ImportContainer,
  ImportContainerInfo, ImportDeclaration, ImportDeclarationElementInfo, JavaElement, JavaElementInfo, JavaModelManager,
  MemberValuePair, OpenableElementInfo, SourceRefElement }
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants
import org.eclipse.jdt.ui.JavaElementImageDescriptor

import scala.collection.Map
import scala.collection.mutable.HashMap

import scala.tools.nsc.symtab.Flags
import scala.tools.nsc.util.{ NoPosition, Position }

import scala.tools.eclipse.ScalaPresentationCompiler
import scala.tools.eclipse.util.ReflectionUtils

trait ScalaStructureBuilder { self : ScalaPresentationCompiler =>

  class StructureBuilderTraverser(scu : ScalaCompilationUnit, unitInfo : OpenableElementInfo, newElements0 : JMap[AnyRef, AnyRef], sourceLength : Int) {
    private val manager = JavaModelManager.getJavaModelManager

    type OverrideInfo = Int
    var overrideInfos : collection.mutable.Map[Symbol, OverrideInfo] = _
    def fillOverrideInfos(c : Symbol) {
      overrideInfos = new collection.mutable.HashMap[Symbol, OverrideInfo]
      val opc = new overridingPairs.Cursor(c)
      while (opc.hasNext) {
        if (!opc.overridden.isClass && opc.overriding.pos.isOpaqueRange) {
          overrideInfos += opc.overriding -> (if (opc.overridden.isDeferred) JavaElementImageDescriptor.IMPLEMENTS else JavaElementImageDescriptor.OVERRIDES)
        }
        opc.next
      }
    }

    def methodOverrideInfo(m : Symbol) = overrideInfos.getOrElse(m, 0)
    
    trait Owner {
      def parent : Owner
      def jdtOwner = this

      def element : JavaElement
      def elementInfo : JavaElementInfo
      def compilationUnitBuilder : CompilationUnitBuilder = parent.compilationUnitBuilder
      
      def isPackage = false
      def isCtor = false
      def isTemplate = false
      def template : Owner = if (parent != null) parent.template else null

      def addPackage(p : PackageDef) : Owner = this
      def addImport(i : Import) : Owner = this
      def addClass(c : ClassDef) : Owner = this
      def addModule(m : ModuleDef) : Owner = this
      def addVal(v : ValDef) : Owner = this
      def addType(t : TypeDef) : Owner = this
      def addDef(d : DefDef) : Owner = this
      def addFunction(f : Function) : Owner = this
      
      def resetImportContainer {}

      def addChild(child : JavaElement) =
        elementInfo match {
          case scalaMember : ScalaMemberElementInfo => scalaMember.addChild0(child)
          case openable : OpenableElementInfo => OpenableElementInfoUtils.addChild(openable, child)
          case _ =>
        }
      
      def modules : Map[Symbol, ScalaElementInfo] = Map.empty 
      def classes : Map[Symbol, (ScalaElement, ScalaElementInfo)] = Map.empty
      
      def complete {
        def addForwarders(classElem : ScalaElement, classElemInfo : ScalaElementInfo, module: Symbol) {
          def conflictsIn(cls: Symbol, name: Name) =
            cls.info.nonPrivateMembers.exists(_.name == name)
          
          /** List of parents shared by both class and module, so we don't add forwarders
           *  for methods defined there - bug #1804 */
          lazy val commonParents = {
            val cps = module.info.baseClasses
            val mps = module.companionClass.info.baseClasses
            cps.filter(mps contains)
          }
          /* the setter doesn't show up in members so we inspect the name */
          def conflictsInCommonParent(name: Name) =
            commonParents exists { cp => name startsWith (cp.name + "$") }
                 
          /** Should method `m' get a forwarder in the mirror class? */
          def shouldForward(m: Symbol): Boolean =
            m.isMethod &&
	    !m.isConstructor &&
	    !m.isStaticMember &&
	    !(m.owner == definitions.ObjectClass) && 
	    !(m.owner == definitions.AnyClass) &&
	    !m.hasFlag(Flags.CASE | Flags.PROTECTED | Flags.DEFERRED) &&
	    !module.isSubClass(module.companionClass) &&
	    !conflictsIn(definitions.ObjectClass, m.name) &&
	    !conflictsInCommonParent(m.name) && 
	    !conflictsIn(module.companionClass, m.name)
          
          assert(module.isModuleClass)
          
          for (m <- module.info.nonPrivateMembers; if shouldForward(m))
            addForwarder(classElem, classElemInfo, module, m)
        }

        def addForwarder(classElem: ScalaElement, classElemInfo : ScalaElementInfo, module: Symbol, d: Symbol) {
          //val moduleName = javaName(module) // + "$"
          //val className = moduleName.substring(0, moduleName.length() - 1)

          val nm = d.name
          
          val fps = for(vps <- d.tpe.paramss; vp <- vps) yield vp
          
          def paramType(sym : Symbol) = {
            val tpe = sym.tpe
            if (sym.isType || tpe != null)
              uncurry.transformInfo(sym, tpe).typeSymbol
            else {
              NoSymbol
            }
          }
          
          val paramTypes = Array(fps.map(v => Signature.createTypeSignature(mapType(paramType(v)), false)) : _*)
          val paramNames = Array(fps.map(n => nme.getterName(n.name).toString.toArray) : _*)
          
          val defElem = 
            if(d.hasFlag(Flags.ACCESSOR))
              new ScalaAccessorElement(classElem, nm.toString, paramTypes)
            else
              new ScalaDefElement(classElem, nm.toString, paramTypes, true, nm.toString, methodOverrideInfo(d))
          resolveDuplicates(defElem)
          classElemInfo.addChild0(defElem)
          
          val defElemInfo = new ScalaSourceMethodInfo
          
          defElemInfo.setArgumentNames(paramNames)
          defElemInfo.setExceptionTypeNames(new Array[Array[Char]](0))
          val tn = manager.intern(mapType(d.tpe.finalResultType.typeSymbol).toArray)
          defElemInfo.asInstanceOf[FnInfo].setReturnType(tn)
  
          val annotsPos = addAnnotations(d, defElemInfo, defElem)
  
          defElemInfo.setFlags0(ClassFileConstants.AccPublic|ClassFileConstants.AccFinal|ClassFileConstants.AccStatic)
          
          val (start, point, end) =
            d.pos match {
              case NoPosition =>
                (module.pos.point, module.pos.point, module.pos.point)
              case pos =>
                (d.pos.startOrPoint, d.pos.point, d.pos.endOrPoint)
            }
            
          val nameEnd = point+defElem.labelName.length-1
            
          defElemInfo.setNameSourceStart0(point)
          defElemInfo.setNameSourceEnd0(nameEnd)
          defElemInfo.setSourceRangeStart0(start)
          defElemInfo.setSourceRangeEnd0(end)
          
          newElements0.put(defElem, defElemInfo)
        } 
        
        for ((m, mInfo) <- modules) {
          val c = m.companionClass
          if (c != NoSymbol) {
            classes.get(c) match {
              case Some((classElem, classElemInfo)) =>
                addForwarders(classElem, classElemInfo, m.moduleClass)
              case _ =>
            }
          } else {
            val className = m.nameString
            
            val classElem = new ScalaClassElement(element, className, true)
            resolveDuplicates(classElem)
            addChild(classElem)
            
            val classElemInfo = new ScalaElementInfo
            classElemInfo.setHandle(classElem)
            classElemInfo.setFlags0(ClassFileConstants.AccSuper|ClassFileConstants.AccFinal|ClassFileConstants.AccPublic)
            classElemInfo.setSuperclassName("java.lang.Object".toArray)
            classElemInfo.setSuperInterfaceNames(null)
            classElemInfo.setNameSourceStart0(mInfo.getNameSourceStart)
            classElemInfo.setNameSourceEnd0(mInfo.getNameSourceEnd)
            classElemInfo.setSourceRangeStart0(mInfo.getDeclarationSourceStart)
            classElemInfo.setSourceRangeEnd0(mInfo.getDeclarationSourceEnd)
            
            newElements0.put(classElem, classElemInfo)
            
            addForwarders(classElem, classElemInfo, m.moduleClass)
          }
        }
      }
    }
    
    trait PackageOwner extends Owner { self =>
      override def addPackage(p : PackageDef) : Owner = {
        //println("Package defn: "+p.name+" ["+this+"]")
        
        new Builder {
          val parent = self
          val element = compilationUnitBuilder.element
          val elementInfo = compilationUnitBuilder.elementInfo
          
          override def isPackage = true
          var completed = !compilationUnitBuilder.element.isInstanceOf[JDTCompilationUnit]
          override def addChild(child : JavaElement) = {
            if (!completed) {
              completed = true
              
              val pkgElem = JavaElementFactory.createPackageDeclaration(compilationUnitBuilder.element.asInstanceOf[JDTCompilationUnit], p.symbol.fullName)
              resolveDuplicates(pkgElem)
              compilationUnitBuilder.addChild(pkgElem)

              val pkgElemInfo = JavaElementFactory.createSourceRefElementInfo
              newElements0.put(pkgElem, pkgElemInfo)
            }
            
            compilationUnitBuilder.addChild(child)
          }
        }
      }
    }
    
    trait ImportContainerOwner extends Owner { self =>
      import SourceRefElementInfoUtils._
      import ImportContainerInfoUtils._
    
      var currentImportContainer : Option[(ImportContainer, ImportContainerInfo)] = None
      
      override def resetImportContainer : Unit = currentImportContainer = None
      
      override def addImport(i : Import) : Owner = {
        //println("Import "+i)
        val prefix = i.expr.symbol.fullName
        val pos = i.pos

        def isWildcard(s: ImportSelector) : Boolean = s.name == nme.WILDCARD

        def addImport(name : String, isWildcard : Boolean) {
          val path = prefix+"."+(if(isWildcard) "*" else name)
          
          val (importContainer, importContainerInfo) = currentImportContainer match {
            case Some(ci) => ci
            case None =>
              val importContainerElem = JavaElementFactory.createImportContainer(element)
              val importContainerElemInfo = new ImportContainerInfo
                
              resolveDuplicates(importContainerElem)
              addChild(importContainerElem)
              newElements0.put(importContainerElem, importContainerElemInfo)
              
              val ci = (importContainerElem, importContainerElemInfo)
              currentImportContainer = Some(ci)
              ci
          }
          
          val importElem = JavaElementFactory.createImportDeclaration(importContainer, path, isWildcard)
          resolveDuplicates(importElem)
        
          val importElemInfo = new ImportDeclarationElementInfo
          setSourceRangeStart(importElemInfo, pos.startOrPoint)
          setSourceRangeEnd(importElemInfo, pos.endOrPoint-1)
        
          val children = getChildren(importContainerInfo)
          if (children.isEmpty)
            setChildren(importContainerInfo, Array[IJavaElement](importElem))
          else
            setChildren(importContainerInfo, children ++ Seq(importElem))
            
          newElements0.put(importElem, importElemInfo)
        }

        i.selectors.foreach(s => addImport(s.name.toString, isWildcard(s)))
        
        self
      }
    }
    
    trait ClassOwner extends Owner { self =>
      override val classes = new HashMap[Symbol, (ScalaElement, ScalaElementInfo)]
    
      override def addClass(c : ClassDef) : Owner = {
        //println("Class defn: "+c.name+" ["+this+"]")
        //println("Parents: "+c.impl.parents)
        
        val name0 = c.name.toString
        val isAnon = name0 == "$anon"
        val name = if (isAnon) "" else name0
        
        val parentTree = c.impl.parents.head
        val superclassType = parentTree.tpe
        val (superclassName, primaryType, interfaceTrees) =
          if (superclassType == null)
            (null, null, c.impl.parents)
          else if (superclassType.typeSymbol.isTrait)
            (null, superclassType.typeSymbol, c.impl.parents)
          else {
            val interfaceTrees0 = c.impl.parents.drop(1) 
            val superclassName0 = superclassType.typeSymbol.fullName
            if (superclassName0 == "java.lang.Object") {
              if (interfaceTrees0.isEmpty)
                ("java.lang.Object".toCharArray, null, interfaceTrees0)
              else
                (null, interfaceTrees0.head.tpe.typeSymbol, interfaceTrees0)
            }
            else
              (superclassName0.toCharArray, superclassType.typeSymbol, interfaceTrees0)   
          }

        val classElem =
          if(c.mods.isTrait)
            new ScalaTraitElement(element, name)
          else if (isAnon) {
            val primaryTypeString = if (primaryType != null) primaryType.name.toString else null
            new ScalaAnonymousClassElement(element, primaryTypeString)
          }
          else
            new ScalaClassElement(element, name, false)
        
        resolveDuplicates(classElem)
        addChild(classElem)
        
        val classElemInfo = new ScalaElementInfo
        classes(c.symbol) = (classElem, classElemInfo)
        
        classElemInfo.setHandle(classElem)
        val mask = ~(if (isAnon) ClassFileConstants.AccPublic else 0)
        classElemInfo.setFlags0(mapModifiers(c.mods) & mask)
        
        val annotsPos = addAnnotations(c.symbol, classElemInfo, classElem)

        classElemInfo.setSuperclassName(superclassName)
        
        val interfaceTypes = interfaceTrees.map(t => (t, t.tpe))
        val interfaceNames = interfaceTypes.map({ case (tree, tpe) => (if (tpe ne null) tpe.typeSymbol.fullName else "null-"+tree).toCharArray })
        classElemInfo.setSuperInterfaceNames(interfaceNames.toArray)
        
        val (start, end) = if (!isAnon) {
          val start0 = c.pos.point 
          (start0, start0 + name.length - 1)
        } else if (primaryType != null) {
          val start0 = parentTree.pos.point
          (start0, start0 + primaryType.name.length - 1)
        } else {
          val start0 = parentTree.pos.point
          (start0, start0 - 1)
        }
        
        classElemInfo.setNameSourceStart0(start)
        classElemInfo.setNameSourceEnd0(end)
        setSourceRange(classElemInfo, c, annotsPos)
        newElements0.put(classElem, classElemInfo)

        fillOverrideInfos(c.symbol)
        
        new Builder {
          val parent = self
          val element = classElem
          val elementInfo = classElemInfo
          
          override def isTemplate = true
          override def template = this
        }
      }
    }
    
    trait ModuleOwner extends Owner { self =>
      override val modules = new HashMap[Symbol, ScalaElementInfo]

      override def addModule(m : ModuleDef) : Owner = {
        //println("Module defn: "+m.name+" ["+this+"]")
        
        val isSynthetic = m.symbol.hasFlag(Flags.SYNTHETIC)
        val moduleElem = new ScalaModuleElement(element, m.name.toString, isSynthetic)
        resolveDuplicates(moduleElem)
        addChild(moduleElem)
        
        val moduleElemInfo = new ScalaElementInfo
        m.symbol match {
          case NoSymbol => ()
          case s => if (s.owner.isPackageClass) modules(s) = moduleElemInfo
        }
        
        moduleElemInfo.setHandle(moduleElem)
        moduleElemInfo.setFlags0(mapModifiers(m.mods)|ClassFileConstants.AccFinal)
        
        val annotsPos = addAnnotations(m.symbol, moduleElemInfo, moduleElem)

        val start = m.pos.point
        val end = start+m.name.length-1
        
        moduleElemInfo.setNameSourceStart0(start)
        moduleElemInfo.setNameSourceEnd0(end)
        if (!isSynthetic)
          setSourceRange(moduleElemInfo, m, annotsPos)
        else {
          moduleElemInfo.setSourceRangeStart0(end)
          moduleElemInfo.setSourceRangeEnd0(end)
        }
        newElements0.put(moduleElem, moduleElemInfo)
        
        val parentTree = m.impl.parents.head
        val superclassType = parentTree.tpe
        val superclassName = (if (superclassType ne null) superclassType.typeSymbol.fullName else "null-"+parentTree).toCharArray
        moduleElemInfo.setSuperclassName(superclassName)
        
        val interfaceTrees = m.impl.parents.drop(1)
{'fraction_non_alphanumeric': 0.08546831548429087, 'fraction_numerical': 0.004378439145612686, 'mean_word_length': 2.2697813890501064, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '144300', 'n_tokens_mistral': 9413, 'n_tokens_neox': 9205, 'n_words': 1887}