1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-05-05 18:34:03 +02:00

Optional function arguments

This commit is contained in:
lippfi 2021-09-21 20:28:02 +03:00
parent c10634f1e3
commit 1dc4dbf7af
5 changed files with 35 additions and 4 deletions
src/com/maddyhome/idea/vim/vimscript
test/org/jetbrains/plugins/ideavim/ex/implementation/statements
vimscript-info

View File

@ -30,6 +30,7 @@ import com.maddyhome.idea.vim.vimscript.model.Executable
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimList
import com.maddyhome.idea.vim.vimscript.model.expressions.Expression
import com.maddyhome.idea.vim.vimscript.model.expressions.Scope
import com.maddyhome.idea.vim.vimscript.model.expressions.Variable
@ -42,7 +43,7 @@ data class DefinedFunctionHandler(private val function: FunctionDeclaration) : F
private val logger = logger<DefinedFunctionHandler>()
override val minimumNumberOfArguments = function.args.size
override val maximumNumberOfArguments = function.args.size
override val maximumNumberOfArguments get() = if (function.hasOptionalArguments) null else function.args.size
override fun doFunction(argumentValues: List<Expression>, editor: Editor, context: DataContext, parent: Executable): VimDataType {
var returnValue: VimDataType? = null
@ -135,6 +136,15 @@ data class DefinedFunctionHandler(private val function: FunctionDeclaration) : F
function
)
}
if (function.hasOptionalArguments) {
VariableService.storeVariable(
Variable(Scope.FUNCTION_VARIABLE, "000"),
VimList(argumentValues.subList(function.args.size, argumentValues.size).map { it.evaluate(editor, context, function) }.toMutableList()),
editor,
context,
function
)
}
VariableService.storeVariable(
Variable(Scope.FUNCTION_VARIABLE, "firstline"),
VimInt(ranges!!.getFirstLine(editor, editor.caretModel.currentCaret) + 1), editor, context, function

View File

@ -16,7 +16,7 @@ data class FunctionDeclaration(
val body: List<Executable>,
val replaceExisting: Boolean,
val flags: Set<FunctionFlag>,
val scriptName: String? = null,
val hasOptionalArguments: Boolean,
) : Executable() {
/**

View File

@ -71,10 +71,11 @@ object ExecutableVisitor : VimscriptBaseVisitor<Executable>() {
val body = ctx.blockMember().mapNotNull { visitBlockMember(it) }
val replaceExisting = ctx.replace != null
val flags = mutableSetOf<FunctionFlag?>()
val hasOptionalArguments = ctx.argumentsDeclaration().ETC() != null
for (flag in ctx.functionFlag()) {
flags.add(FunctionFlag.getByName(flag.text))
}
return FunctionDeclaration(functionScope, functionName, args, body, replaceExisting, flags.filterNotNull().toSet())
return FunctionDeclaration(functionScope, functionName, args, body, replaceExisting, flags.filterNotNull().toSet(), hasOptionalArguments)
}
override fun visitTryStatement(ctx: VimscriptParser.TryStatementContext): Executable {

View File

@ -540,4 +540,24 @@ class FunctionDeclarationTest : VimTestCase() {
typeText(commandToKeys("delf! F1"))
}
fun `test optional arguments`() {
configureByText("\n")
typeText(
commandToKeys(
"" +
"function GetOptionalArgs(name, ...) |" +
" return a:000 | " +
"endfunction"
)
)
typeText(commandToKeys("echo GetOptionalArgs('this arg is not optional')"))
assertExOutput("[]\n")
typeText(
commandToKeys(
"echo GetOptionalArgs('this arg is not optional', 42, 'optional arg')"
)
)
assertExOutput("[42, 'optional arg']\n")
}
}

View File

@ -22,7 +22,7 @@
- [x] `range` function flag
- [x] `call` command
- [ ] function as method
- [ ] optional arguments `...`
- [x] optional arguments `...`
- [ ] funcref type
- [ ] lambdas
- [ ] default value in functions e.g. `function F1(a, b = 10)`