Skip to content

Commit

Permalink
Formalised type widening behaviour for overidden fields/methods.
Browse files Browse the repository at this point in the history
Essentially, an explicit type annotation will always take
precedence over an implicitly inferred type. Thus, if you wish
a sub-class to narrow an overridden type, you ought to do so
explicitly with a type annotation.

The only time the child's type will automatically narrow a
parent's type is if the parent did not provide an explicit type
annotation for the field/method.
  • Loading branch information
Benjamin-Dobell committed Jan 8, 2021
1 parent 9c0f626 commit 230b7fb
Show file tree
Hide file tree
Showing 61 changed files with 1,053 additions and 210 deletions.
10 changes: 9 additions & 1 deletion gen/com/tang/intellij/lua/comment/parser/LuaDocParser.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions gen/com/tang/intellij/lua/comment/psi/LuaDocArrTy.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions gen/com/tang/intellij/lua/comment/psi/LuaDocClassRef.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions gen/com/tang/intellij/lua/comment/psi/LuaDocTableField.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions gen/com/tang/intellij/lua/comment/psi/LuaDocTagField.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions gen/com/tang/intellij/lua/comment/psi/LuaDocTagReturn.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions gen/com/tang/intellij/lua/psi/LuaClassMethodDefStat.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions gen/com/tang/intellij/lua/psi/LuaFuncDefStat.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions gen/com/tang/intellij/lua/psi/LuaIndexExpr.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions gen/com/tang/intellij/lua/psi/LuaNameExpr.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions gen/com/tang/intellij/lua/psi/LuaTableField.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions gen/com/tang/intellij/lua/psi/impl/LuaFuncDefStatImpl.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions gen/com/tang/intellij/lua/psi/impl/LuaIndexExprImpl.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions gen/com/tang/intellij/lua/psi/impl/LuaNameExprImpl.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions gen/com/tang/intellij/lua/psi/impl/LuaTableFieldImpl.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,10 @@ class LuaParameterInfoHandler : ParameterInfoHandler<LuaArgs, ParameterInfoType>
o.sig.processParameters(null, o.isColonStyle) { idx, pi ->
if (idx > 0) append(", ")
if (idx == index) start = length
val ty = pi.ty ?: Ty.UNKNOWN
append(pi.name)
append(": ")
append(pi.ty.displayName)
append(ty.displayName)
if (idx == index) end = length
true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.util.PsiTreeUtil
import com.tang.intellij.lua.project.LuaSettings
import com.tang.intellij.lua.psi.*
import com.tang.intellij.lua.search.PsiSearchContext
Expand Down Expand Up @@ -82,7 +83,7 @@ class AssignTypeInspection : StrictInspection() {
}
}

fun inspectAssignment(assignees: List<LuaTypeGuessable>, expressions: List<LuaExpression<*>>?) {
fun inspectAssignment(statement: LuaStatement?, assignees: List<LuaTypeGuessable>, expressions: List<LuaExpression<*>>?) {
if (expressions == null || expressions.size == 0) {
return
}
Expand All @@ -91,6 +92,7 @@ class AssignTypeInspection : StrictInspection() {
var assigneeIndex = 0
var variadicTy: ITy? = null
var lastExpressionFirstAssigneeIndex = 0
val isClassDeclaration = statement?.comment?.tagClass != null

for (expressionIndex in 0 until expressions.size) {
val isLastExpression = expressionIndex == expressions.size - 1
Expand Down Expand Up @@ -157,7 +159,7 @@ class AssignTypeInspection : StrictInspection() {
value = variadicTy
}

if (assignees.size == 1 && LuaPsiTreeUtil.findAncestorOfType(assignee, LuaStatement::class.java)?.comment?.tagClass != null) {
if (isClassDeclaration) {
if (value !is TyTable) {
myHolder.registerProblem(expression, "Type mismatch. Required: 'table' Found: '%s'".format(value.displayName))
}
Expand Down Expand Up @@ -218,12 +220,22 @@ class AssignTypeInspection : StrictInspection() {

override fun visitAssignStat(o: LuaAssignStat) {
super.visitAssignStat(o)
inspectAssignment(o.varExprList.expressionList, o.valueExprList?.expressionList)
inspectAssignment(o, o.varExprList.expressionList, o.valueExprList?.expressionList)
}

override fun visitLocalDefStat(o: LuaLocalDefStat) {
super.visitLocalDefStat(o)
inspectAssignment(o.localDefList, o.exprList?.expressionList)
inspectAssignment(o, o.localDefList, o.exprList?.expressionList)
}

override fun visitTableField(o: LuaTableField) {
super.visitTableField(o)

o.valueExpr?.let { valueExpr ->
if (o.isExplicitlyTyped) {
inspectAssignment(null, listOf(o), listOf(valueExpr))
}
}
}
}
}
18 changes: 6 additions & 12 deletions src/main/java/com/tang/intellij/lua/comment/LuaCommentUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,21 @@ object LuaCommentUtil {
val parent = element.parent

if (parent is LuaTableField) {
val tableFieldComment = parent.comment

// If we encounter a table field with an EmmyDoc, that isn't a type definition, return that comment.
if (tableFieldComment?.findTag(LuaDocTagType::class.java) == null) {
return tableFieldComment
}
// If the closure is being assigned to table field, use the field's comment
return parent.comment
}

val grandParent = element.parent.parent
val assignmentComment = if (grandParent is LuaLocalDefStat && grandParent.localDefList.size == 1) {
val assignmentComment = if (grandParent is LuaLocalDefStat) {
grandParent.comment
} else if (grandParent is LuaAssignStat && grandParent.varExprList.expressionList.size == 1) {
} else if (grandParent is LuaAssignStat) {
grandParent.comment
} else {
null
}

// If we encounter a closure assignment with an EmmyDoc, that isn't a type definition, return that comment.
if (assignmentComment?.findTag(LuaDocTagType::class.java) == null) {
return assignmentComment
}
// If the closure is a value of a (single value) assignment statement, use that comment.
return assignmentComment
}

return null
Expand Down
Loading

3 comments on commit 230b7fb

@adriweb
Copy link

@adriweb adriweb commented on 230b7fb Jan 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be similarly feasible to make it so that overriding a variable typed with MyClass|nil by MyClass would "get rid" of the nil part for the subsequent usage of that variable?
Let's say I have this:

--- assume MyClass being a correctly annotated class.
---@type table<string,MyClass|nil>
local tbl = {}
tbl.foo = MyClass()
tbl.foo:doThing(42, true)

Here the analyzer is a bit confused, because it correctly understands the call and the arguments (hints appear correctly, types are correct, etc.), but it does say No such member 'doThing' found on type 'nil'.
I'm testing on the latest master btw.

@Benjamin-Dobell
Copy link
Owner Author

@Benjamin-Dobell Benjamin-Dobell commented on 230b7fb Jan 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adriweb This commit is regarding the inferred type of members when inheriting from a base class. Where as it looks like you're after nil tracking. There's already an issue for nil tracking, #4. However, yes that's on my list of features to implement - a few features are ahead of it though.

@adriweb
Copy link

@adriweb adriweb commented on 230b7fb Jan 9, 2021 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.