mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 05:10:55 +00:00
idea: implement function call completion (limited)
This commit is contained in:
parent
d12aadf18c
commit
c92a111af7
@ -0,0 +1,7 @@
|
|||||||
|
package gay.pizza.pork.parser
|
||||||
|
|
||||||
|
fun CharSource.readToString(): String = buildString {
|
||||||
|
while (peek() != CharSource.NullChar) {
|
||||||
|
append(next())
|
||||||
|
}
|
||||||
|
}
|
@ -8,15 +8,34 @@ import gay.pizza.pork.idea.psi.gen.PorkElement
|
|||||||
class PorkFunctionReference(element: PorkElement, textRange: TextRange) : PorkReference(element, textRange) {
|
class PorkFunctionReference(element: PorkElement, textRange: TextRange) : PorkReference(element, textRange) {
|
||||||
override fun resolve(): PorkElement? {
|
override fun resolve(): PorkElement? {
|
||||||
val functionName = canonicalText
|
val functionName = canonicalText
|
||||||
for (file in getRelevantFiles()) {
|
val functionDefinitions = findFunctionDefinitions(functionName)
|
||||||
val thisFileFunctionDefinitions = PsiTreeUtil.collectElementsOfType(file, FunctionDefinitionElement::class.java)
|
if (functionDefinitions.isNotEmpty()) {
|
||||||
val thisFileFoundFunctionDefinition = thisFileFunctionDefinitions.firstOrNull {
|
return functionDefinitions.first()
|
||||||
it.name == functionName
|
|
||||||
}
|
|
||||||
if (thisFileFoundFunctionDefinition != null) {
|
|
||||||
return thisFileFoundFunctionDefinition
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getVariants(): Array<Any> {
|
||||||
|
return findFunctionDefinitions().toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findFunctionDefinitions(name: String? = null): List<FunctionDefinitionElement> {
|
||||||
|
val foundFunctionDefinitions = mutableListOf<FunctionDefinitionElement>()
|
||||||
|
for (file in getRelevantFiles()) {
|
||||||
|
val fileFunctionDefinitions = PsiTreeUtil.collectElementsOfType(file, FunctionDefinitionElement::class.java)
|
||||||
|
if (name != null) {
|
||||||
|
val fileFoundDefinition = fileFunctionDefinitions.firstOrNull {
|
||||||
|
it.name == name
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileFoundDefinition != null) {
|
||||||
|
foundFunctionDefinitions.add(fileFoundDefinition)
|
||||||
|
return foundFunctionDefinitions
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foundFunctionDefinitions.addAll(fileFunctionDefinitions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return foundFunctionDefinitions
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.psi.PsiReferenceBase
|
import com.intellij.psi.PsiReferenceBase
|
||||||
|
import com.intellij.psi.search.FilenameIndex
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.psi.util.childrenOfType
|
import com.intellij.psi.util.childrenOfType
|
||||||
import gay.pizza.pork.idea.psi.gen.ImportDeclarationElement
|
import gay.pizza.pork.idea.psi.gen.ImportDeclarationElement
|
||||||
@ -13,9 +14,12 @@ import gay.pizza.pork.idea.psi.gen.SymbolElement
|
|||||||
|
|
||||||
abstract class PorkReference(element: PorkElement, textRange: TextRange) : PsiReferenceBase<PsiElement>(element, textRange) {
|
abstract class PorkReference(element: PorkElement, textRange: TextRange) : PsiReferenceBase<PsiElement>(element, textRange) {
|
||||||
fun getRelevantFiles(): List<PsiFile> {
|
fun getRelevantFiles(): List<PsiFile> {
|
||||||
val containingFile = element.containingFile
|
val containingFile = element.containingFile ?: return emptyList()
|
||||||
|
if (containingFile.virtualFile == null) {
|
||||||
|
return getAllProjectPorkFiles()
|
||||||
|
}
|
||||||
val importDeclarationElements = PsiTreeUtil.collectElementsOfType(containingFile, ImportDeclarationElement::class.java)
|
val importDeclarationElements = PsiTreeUtil.collectElementsOfType(containingFile, ImportDeclarationElement::class.java)
|
||||||
val files = mutableListOf<PsiFile>(containingFile)
|
val files = mutableListOf(containingFile)
|
||||||
for (importDeclaration in importDeclarationElements) {
|
for (importDeclaration in importDeclarationElements) {
|
||||||
val symbolElements = importDeclaration.childrenOfType<SymbolElement>()
|
val symbolElements = importDeclaration.childrenOfType<SymbolElement>()
|
||||||
val importType = importDeclaration.childrenOfType<SymbolElement>().first().text
|
val importType = importDeclaration.childrenOfType<SymbolElement>().first().text
|
||||||
@ -25,10 +29,17 @@ abstract class PorkReference(element: PorkElement, textRange: TextRange) : PsiRe
|
|||||||
|
|
||||||
val basicImportPath = symbolElements.drop(1).joinToString("/") { it.text.trim() }
|
val basicImportPath = symbolElements.drop(1).joinToString("/") { it.text.trim() }
|
||||||
val actualImportPath = "../${basicImportPath}.pork"
|
val actualImportPath = "../${basicImportPath}.pork"
|
||||||
val virtualFile = containingFile.virtualFile.findFileByRelativePath(actualImportPath) ?: continue
|
val virtualFile = containingFile.virtualFile?.findFileByRelativePath(actualImportPath) ?: continue
|
||||||
val psiFile = PsiManager.getInstance(element.project).findFile(virtualFile) ?: continue
|
val psiFile = PsiManager.getInstance(element.project).findFile(virtualFile) ?: continue
|
||||||
files.add(psiFile)
|
files.add(psiFile)
|
||||||
}
|
}
|
||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getAllProjectPorkFiles(): List<PsiFile> {
|
||||||
|
val porkVirtualFiles = FilenameIndex.getAllFilesByExt(element.project, "pork")
|
||||||
|
return porkVirtualFiles.mapNotNull { virtualFile ->
|
||||||
|
PsiManager.getInstance(element.project).findFile(virtualFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package gay.pizza.pork.tool
|
||||||
|
|
||||||
|
import com.github.ajalt.clikt.core.CliktCommand
|
||||||
|
import com.github.ajalt.clikt.parameters.arguments.argument
|
||||||
|
import com.github.ajalt.clikt.parameters.arguments.default
|
||||||
|
import gay.pizza.dough.fs.PlatformFsProvider
|
||||||
|
import gay.pizza.dough.fs.createDirectories
|
||||||
|
import gay.pizza.dough.fs.exists
|
||||||
|
import gay.pizza.dough.fs.writeString
|
||||||
|
import gay.pizza.pork.parser.readToString
|
||||||
|
import gay.pizza.pork.stdlib.PorkStdlib
|
||||||
|
|
||||||
|
class CopyStdlibCommand : CliktCommand(help = "Copy Stdlib", name = "copy-stdlib") {
|
||||||
|
val output by argument("output").default("stdlib")
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
val outputFsPath = PlatformFsProvider.resolve(output)
|
||||||
|
for (filePath in PorkStdlib.files) {
|
||||||
|
val outputFilePath = outputFsPath.resolve(filePath)
|
||||||
|
if (outputFilePath.parent?.exists() == false) {
|
||||||
|
outputFilePath.parent?.createDirectories()
|
||||||
|
}
|
||||||
|
outputFilePath.writeString(PorkStdlib.loadAsCharSource(filePath).readToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,8 @@ class RootCommand : CliktCommand(
|
|||||||
ParseCommand(),
|
ParseCommand(),
|
||||||
AstCommand(),
|
AstCommand(),
|
||||||
AttributeCommand(),
|
AttributeCommand(),
|
||||||
ScopeAnalysisCommand()
|
ScopeAnalysisCommand(),
|
||||||
|
CopyStdlibCommand()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user