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

com.jtransc.ast.ast_references.kt Maven / Gradle / Ivy

Go to download

JVM AOT compiler currently generating JavaScript, C++, Haxe, with initial focus on Kotlin and games.

There is a newer version: 0.6.8
Show newest version
package com.jtransc.ast

import com.jtransc.annotation.JTranscAddFileList
import com.jtransc.annotation.JTranscAddMembers
import com.jtransc.annotation.JTranscAddMembersList
import com.jtransc.annotation.JTranscMethodBodyList
import com.jtransc.annotation.haxe.*
import com.jtransc.ast.template.CommonTagHandler
import com.jtransc.ast.treeshaking.GetClassTemplateReferences
import com.jtransc.gen.TargetName
import com.jtransc.template.Minitemplate

object References {
	private val bl = JTranscMethodBodyList::class.java

	fun get(clazz: AstClass, targetName: TargetName) = clazz.getClassReferences(targetName)

	fun AstClass.getClassReferences(targetName: TargetName): List {
		val me = AstType.REF(this.fqname)
		val parent = if (this.extending != null) AstType.REF(this.extending) else null
		val interfaces = this.implementing.map { AstType.REF(it) }
		val fields = this.fields.flatMap { it.getClassReferences(targetName) }
		val methods = this.methods.flatMap { it.getClassReferences(targetName) }
		val annotations = this.annotations.getClassReferences(targetName)
		val annotations2 = this.annotationsList.getClassReferencesExtra(this, this.program, targetName)
		return (listOf(me) + listOf(parent) + interfaces + fields + methods + annotations + annotations2).filterNotNull()
	}

	fun AstAnnotationList.getClassReferencesExtra(clazz: AstClass, program: AstProgram, targetName: TargetName): List {
		val out = arrayListOf()
		for (file in this.getTypedList(JTranscAddFileList::value).filter { it.process && targetName.matches(it.target) }) {
			val possibleFiles = listOf(file.prepend, file.append, file.prependAppend)
			for (pf in possibleFiles.filter { !it.isNullOrEmpty() }) {
				val filecontent = program.resourcesVfs[pf].readString()
				out += GetClassTemplateReferences(program, filecontent, clazz.name).map { AstType.REF(it) }
			}
		}

		for (member in this.getTypedList(JTranscAddMembersList::value).filter { targetName.matches(it.target) }) {
			out += GetClassTemplateReferences(program, member.value.joinToString("\n"), clazz.name).map { AstType.REF(it) }
		}

		// @TODO: This should be unified!
		if (targetName.matches("haxe")) {
			val haxeAddFilesTemplate = this.getTyped()
			if (haxeAddFilesTemplate != null) {
				for (file in haxeAddFilesTemplate.value) {
					val filecontent = program.resourcesVfs[file].readString()
					out += GetClassTemplateReferences(program, filecontent, clazz.name).map { AstType.REF(it) }
				}
			}
			val haxeAddMembers = this.getTyped()
			if (haxeAddMembers != null) {
				out += GetClassTemplateReferences(program, haxeAddMembers.value.joinToString("\n"), clazz.name).map { AstType.REF(it) }
			}
		}
		return out
	}

	fun AstField.getClassReferences(targetName: TargetName): List {
		return this.genericType.getRefClasses() + this.annotations.getClassReferences(targetName)
	}

	fun AstMethod.getClassReferences(targetName: TargetName): List {
		val clazzFqname = this.containingClass.name
		val signatureRefs = this.genericMethodType.getRefClasses()
		val annotations = this.annotations.getClassReferences(targetName)
		val parameterAnnotations = this.parameterAnnotations.flatMap { it }.getClassReferences(targetName)
		val templateRefs = arrayListOf()
		//this.annotationsList.list.filter { it.type.name.simpleName == "JsMethodBody" }
		val methodBodyList = this.annotationsList.getBodiesForTarget(targetName)
		val haxeMethodBodyList = this.annotationsList.getTypedList(HaxeMethodBodyList::value).filter { targetName.haxeMatches(it.target) }
		val refs = if (methodBodyList.isEmpty() && haxeMethodBodyList.isEmpty()) this.body?.getClassReferences() ?: listOf() else listOf()

		for (methodBody in methodBodyList) {
			templateRefs += GetClassTemplateReferences(program, methodBody.value, clazzFqname).map { AstType.REF(it) }
		}

		for (methodBody in haxeMethodBodyList) {
			templateRefs += GetClassTemplateReferences(program, methodBody.value, clazzFqname).map { AstType.REF(it) }
		}

		if (targetName.haxeMatches("")) {
			val haxeMethodBodyPre = this.annotationsList.getTyped()
			val haxeMethodBodyPost = this.annotationsList.getTyped()

			if (haxeMethodBodyPre != null) templateRefs += GetClassTemplateReferences(program, haxeMethodBodyPre.value, clazzFqname).map { AstType.REF(it) }
			if (haxeMethodBodyPost != null) templateRefs += GetClassTemplateReferences(program, haxeMethodBodyPost.value, clazzFqname).map { AstType.REF(it) }
		}

		return signatureRefs + refs + annotations + parameterAnnotations + templateRefs
	}

	fun List.getClassReferences(targetName: TargetName): List {
		return this.flatMap { it.getClassReferences(targetName) }
	}

	fun Any?.getClassReferences(targetName: TargetName): List {
		return when (this) {
			null -> listOf()
			is List<*> -> this.flatMap { it.getClassReferences(targetName) }
			is AstAnnotation -> this.getClassReferences(targetName)
			is AstBody -> this.getClassReferences()
			is AstStm -> this.getClassReferences()
			is AstMethod -> this.getClassReferences(targetName)
			is AstField -> this.getClassReferences(targetName)
			is AstClass -> this.getClassReferences(targetName)
			else -> listOf()
		}
	}

	fun AstAnnotation.getClassReferences(targetName: TargetName): List {
		return listOf(this.type) + this.elements.values.getClassReferences(targetName)
	}

	fun AstBody.getClassReferences(): List {
		val locals = this.locals.flatMap { it.type.getRefClasses() }
		val traps = this.traps.map { it.exception }
		val stms = this.stm.getClassReferences()
		return locals + traps + stms
	}

	fun AstStm.getClassReferences(): List {
		val refs = ReferencesVisitor()
		refs.visit(this)
		return (refs.classReferences + refs.fieldReferences.map { it.classRef } + refs.methodReferences.flatMap { it.allClassRefs }).toList()
	}

	class ReferencesVisitor : AstVisitor() {
		val classReferences = hashSetOf()
		val fieldReferences = hashSetOf()
		val methodReferences = hashSetOf()

		override fun visit(ref: AstType.REF) {
			super.visit(ref)
			classReferences += ref
		}

		override fun visit(ref: AstFieldRef) {
			super.visit(ref)
			fieldReferences += ref
		}

		override fun visit(ref: AstMethodRef) {
			super.visit(ref)
			methodReferences += ref
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy