Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add rules param.name, param.type #1128

Merged
merged 1 commit into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ object ClassExportRuleKeys {
BooleanRuleMode.ANY
)

val PARAM_NAME: RuleKey<String> = SimpleRuleKey(
"param.name",
StringRuleMode.SINGLE
)

val PARAM_TYPE: RuleKey<String> = SimpleRuleKey(
"param.type",
StringRuleMode.SINGLE
)

val PARAM_DEFAULT_VALUE: RuleKey<String> = SimpleRuleKey(
"param.default.value",
StringRuleMode.MERGE_DISTINCT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import com.itangcent.intellij.jvm.element.ExplicitParameter
import kotlin.reflect.KClass

interface ExportContext : Extensible {
/**
* the parent context, allowing navigation up the context hierarchy.
*/
fun parent(): ExportContext?

/**
Expand All @@ -23,22 +26,45 @@ interface ExportContext : Extensible {
fun psi(): PsiElement
}

/**
* Extends ExportContext for contexts dealing with variables (methods or parameters).
*/
interface VariableExportContext : ExportContext {

/**
* the name of the variable.
*/
fun name(): String

/**
* the type of the variable, which may be null if the type is not resolved.
*/
fun type(): DuckType?

/**
* the explicit element representation of the variable.
*/
fun element(): ExplicitElement<*>

/**
* Sets a resolved name for the variable, typically used for renaming.
*/
fun setResolvedName(name: String)
}

//region kits of ExportContext

/**
* find specific contexts by type.
*/
@Suppress("UNCHECKED_CAST")
fun <T : ExportContext> ExportContext.findContext(condition: KClass<T>): T? {
return findContext { condition.isInstance(it) } as? T
}

/**
* find specific contexts by condition.
*/
fun ExportContext.findContext(condition: (ExportContext) -> Boolean): ExportContext? {
var exportContext: ExportContext? = this
while (exportContext != null) {
Expand All @@ -50,39 +76,58 @@ fun ExportContext.findContext(condition: (ExportContext) -> Boolean): ExportCont
return null
}

fun <T> ExportContext.findExt(attr: String): T? {
var exportContext: ExportContext? = this
while (exportContext != null) {
exportContext.getExt<T>(attr)?.let { return it }
exportContext = exportContext.parent()
}
return null
}

//endregion

/**
* Base context with no parent, typically used for top-level classes.
*/
abstract class RootExportContext :
SimpleExtensible(), ExportContext {
override fun parent(): ExportContext? {
return null
}
}

/**
* General purpose context implementation with a specified parent context.
*/
abstract class AbstractExportContext(private val parent: ExportContext) :
SimpleExtensible(), ExportContext {
SimpleExtensible(), VariableExportContext {

private var resolvedName: String? = null

override fun parent(): ExportContext? {
return this.parent
}

/**
* Returns the name of the element.
*
* @return the element name.
*/
override fun name(): String {
return resolvedName ?: element().name()
}

override fun setResolvedName(name: String) {
this.resolvedName = name
}
}

/**
* Context specifically for a class
*/
class ClassExportContext(val cls: PsiClass) : RootExportContext() {
override fun psi(): PsiClass {
return cls
}
}

/**
* Context for a method, containing specifics about the method being exported.
*/
class MethodExportContext(
private val parent: ExportContext,
parent: ExportContext,
private val method: ExplicitMethod
) : AbstractExportContext(parent), VariableExportContext {

Expand Down Expand Up @@ -113,19 +158,27 @@ class MethodExportContext(
}
}

class ParameterExportContext(
private val parent: ExportContext,
private val parameter: ExplicitParameter
) : AbstractExportContext(parent), VariableExportContext {
/**
* Context for a parameter, containing specifics about the parameter being exported.
*/
interface ParameterExportContext : VariableExportContext {

/**
* Returns the name of the element.
*
* @return the element name.
*/
override fun name(): String {
return parameter.name()
}
override fun element(): ExplicitParameter

override fun psi(): PsiParameter
}

fun ParameterExportContext(
parent: ExportContext,
parameter: ExplicitParameter
): ParameterExportContext {
return ParameterExportContextImpl(parent, parameter)
}

class ParameterExportContextImpl(
parent: ExportContext,
private val parameter: ExplicitParameter
) : AbstractExportContext(parent), ParameterExportContext {

/**
* Returns the type of the variable.
Expand All @@ -145,18 +198,30 @@ class ParameterExportContext(
}
}

/**
* retrieve ClassExportContext based on the current context.
*/
fun ExportContext.classContext(): ClassExportContext? {
return this.findContext(ClassExportContext::class)
}

/**
* retrieve MethodExportContext based on the current context.
*/
fun ExportContext.methodContext(): MethodExportContext? {
return this.findContext(MethodExportContext::class)
}

/**
* retrieve ParameterExportContext based on the current context.
*/
fun ExportContext.paramContext(): ParameterExportContext? {
return this.findContext(ParameterExportContext::class)
}

/**
* Searches for an extended property, first locally then up the context hierarchy.
*/
fun <T> ExportContext.searchExt(attr: String): T? {
this.getExt<T>(attr)?.let { return it }
this.parent()?.searchExt<T>(attr)?.let { return it }
Expand Down
Loading
Loading