Skip to content

Commit db62b0e

Browse files
committed
configuration & require path completion & code refactoring
1 parent ea63f21 commit db62b0e

File tree

26 files changed

+1024
-189
lines changed

26 files changed

+1024
-189
lines changed

EmmyLua-Common/src/main/ext/com/tang/intellij/lua/IConfiguration.kt

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.tang.intellij.lua
2+
3+
import com.intellij.openapi.project.Project
4+
import com.intellij.openapi.util.Key
5+
6+
interface IVSCodeSettings {
7+
companion object {
8+
val KEY = Key.create<IVSCodeSettings>(IVSCodeSettings::class.java.name)
9+
10+
fun get(project: Project): IVSCodeSettings {
11+
return KEY.get(project)
12+
}
13+
}
14+
val isVSCode: Boolean
15+
val showCodeLens: Boolean
16+
val completionCaseSensitive: Boolean
17+
val sourceRoots: List<String>
18+
19+
fun matchFile(name: String): Boolean
20+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package com.tang.intellij.lua.configuration
2+
3+
class Pattern(pattern: String, private val ignoreCase: Boolean) {
4+
private var value: String? = null
5+
private val values: Array<String>
6+
7+
private var index: Int = 0
8+
9+
private val isExhausted: Boolean
10+
get() = index >= values.size
11+
12+
private val isLast: Boolean
13+
get() = index >= values.size - 1
14+
15+
init {
16+
var pattern = pattern
17+
18+
pattern = pattern.replace('\\', '/')
19+
pattern = pattern.replace("\\*\\*[^/]".toRegex(), "**/*")
20+
pattern = pattern.replace("[^/]\\*\\*".toRegex(), "*/**")
21+
if (ignoreCase) pattern = pattern.toLowerCase()
22+
23+
values = pattern.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
24+
value = values[0]
25+
}
26+
27+
fun matches(fileName: String): Boolean {
28+
var fileName = fileName
29+
val value = this.value
30+
if (value == "**") return true
31+
32+
if (ignoreCase) fileName = fileName.toLowerCase()
33+
34+
// Shortcut if no wildcards.
35+
if (value!!.indexOf('*') == -1 && value.indexOf('?') == -1) return fileName == value
36+
37+
var i = 0
38+
var j = 0
39+
val fileNameLength = fileName.length
40+
val valueLength = value.length
41+
while (i < fileNameLength && j < valueLength) {
42+
val c = value[j]
43+
if (c == '*') break
44+
if (c != '?' && c != fileName[i]) return false
45+
i++
46+
j++
47+
}
48+
49+
// If reached end of pattern without finding a * wildcard, the match has to fail if not same length.
50+
if (j == valueLength) return fileNameLength == valueLength
51+
52+
var cp = 0
53+
var mp = 0
54+
while (i < fileNameLength) {
55+
if (j < valueLength) {
56+
val c = value[j]
57+
if (c == '*') {
58+
if (j++ >= valueLength) return true
59+
mp = j
60+
cp = i + 1
61+
continue
62+
}
63+
if (c == '?' || c == fileName[i]) {
64+
j++
65+
i++
66+
continue
67+
}
68+
}
69+
j = mp
70+
i = cp++
71+
}
72+
73+
// Handle trailing asterisks.
74+
while (j < valueLength && value[j] == '*')
75+
j++
76+
77+
return j >= valueLength
78+
}
79+
80+
private fun nextValue(): String? {
81+
return if (index + 1 == values.size) null else values[index + 1]
82+
}
83+
84+
fun incr(fileName: String): Boolean {
85+
if (value == "**") {
86+
if (index == values.size - 1) return false
87+
incr()
88+
if (matches(fileName))
89+
incr()
90+
else {
91+
decr()
92+
return false
93+
}
94+
} else
95+
incr()
96+
return true
97+
}
98+
99+
private fun incr() {
100+
index++
101+
if (index >= values.size)
102+
value = null
103+
else
104+
value = values[index]
105+
}
106+
107+
private fun decr() {
108+
index--
109+
if (index > 0 && values[index - 1] == "**") index--
110+
value = values[index]
111+
}
112+
113+
private fun reset() {
114+
index = 0
115+
value = values[0]
116+
}
117+
118+
fun wasFinalMatch(): Boolean {
119+
return isExhausted || isLast && value == "**"
120+
}
121+
122+
companion object {
123+
fun match(pattern: String, value: String): Boolean {
124+
val p = Pattern(pattern, false)
125+
val arr = value.split("/")
126+
for (s in arr) {
127+
if (p.matches(s)) {
128+
p.incr(s)
129+
continue
130+
}
131+
break
132+
}
133+
return p.wasFinalMatch()
134+
}
135+
}
136+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.tang.intellij.lua.configuration
2+
3+
import com.intellij.openapi.project.Project
4+
import com.intellij.openapi.util.Key
5+
import com.intellij.util.ThreeState
6+
import com.tang.lsp.FileURI
7+
import java.io.File
8+
9+
interface IConfigurationStructure {
10+
val sourceRoots: List<ISourceRoot>
11+
}
12+
13+
interface ISourceRoot {
14+
val absoluteDir: FileURI?
15+
16+
fun relative(path: String): String?
17+
18+
fun isInclude(uri: FileURI): ThreeState
19+
20+
fun isExclude(uri: FileURI): ThreeState
21+
}
22+
23+
interface IConfigurationManager {
24+
companion object {
25+
val KEY = Key.create<IConfigurationManager>(IConfigurationManager::class.java.name)
26+
27+
fun get(project: Project): IConfigurationManager {
28+
return KEY.get(project)
29+
}
30+
}
31+
32+
val sourceRoots: Array<ISourceRoot>
33+
34+
val completionCaseSensitive: Boolean
35+
36+
fun isInclude(file: File): ThreeState
37+
38+
fun isInclude(uri: FileURI): ThreeState
39+
40+
fun isExclude(uri: FileURI): ThreeState
41+
42+
fun getConfigurationFor(root: FileURI): IConfigurationStructure?
43+
}

EmmyLua-Common/src/main/ext/com/tang/intellij/lua/editor/completion/CompletionService.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import com.intellij.codeInsight.lookup.LookupElement
88
import com.intellij.lang.PsiBuilderFactory
99
import com.intellij.psi.PsiFile
1010
import com.intellij.util.Consumer
11-
import com.tang.intellij.lua.IConfiguration
11+
import com.tang.intellij.lua.configuration.IConfigurationManager
1212
import com.tang.intellij.lua.lang.LuaParserDefinition
1313
import com.tang.intellij.lua.lexer.LuaLexer
1414
import com.tang.intellij.lua.parser.LuaParser
@@ -35,8 +35,8 @@ object CompletionService {
3535
LuaDocCompletionContributor()
3636
)
3737

38-
fun collectCompletion(psi: PsiFile, pos: Int, config: IConfiguration, consumer: Consumer<LookupElement>) {
39-
//val element = psi.findElementAt(pos)
38+
fun collectCompletion(psi: PsiFile, pos: Int, consumer: Consumer<LookupElement>) {
39+
val config = IConfigurationManager.get(psi.project)
4040
val text = psi.text.replaceRange(pos, pos, "emmy")
4141

4242
val parser = LuaParser()

EmmyLua-Common/src/main/ext/com/tang/intellij/lua/editor/completion/LuaCompletionContributor.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class LuaCompletionContributor : CompletionContributor() {
6464
6565
extend(CompletionType.BASIC, IN_TABLE_FIELD, TableCompletionProvider())*/
6666

67+
// require 路径提示
68+
extend(CompletionType.BASIC, SHOW_REQUIRE_PATH, RequirePathCompletionProvider())
6769
//提示属性, 提示方法
6870
extend(CompletionType.BASIC, SHOW_CLASS_FIELD, ClassMemberCompletionProvider())
6971
//提示全局函数,local变量,local函数
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package com.tang.intellij.lua.fs
2+
3+
import com.intellij.openapi.project.Project
4+
import com.intellij.openapi.util.Key
5+
import com.intellij.util.ThreeState
6+
import com.tang.intellij.lua.configuration.IConfigurationManager
7+
import com.tang.intellij.lua.configuration.ISourceRoot
8+
import com.tang.lsp.FileURI
9+
import java.io.File
10+
11+
interface IFileCollection {
12+
val root: FileURI
13+
val files: List<FileURI>
14+
}
15+
16+
interface IFileScopeProvider {
17+
fun isInclude(uri: FileURI): ThreeState
18+
fun isExclude(uri: FileURI): ThreeState
19+
fun findAllFiles(manager: FileManager): List<IFileCollection>
20+
fun getSourceRoots(project: Project): Array<ISourceRoot>
21+
}
22+
23+
class FileCollection(
24+
override val root: FileURI,
25+
override val files: List<FileURI>
26+
) : IFileCollection
27+
28+
interface IFileManager {
29+
fun addProvider(provider: IFileScopeProvider)
30+
fun isInclude(file: File): Boolean
31+
fun isInclude(uri: FileURI): Boolean
32+
fun isExclude(uri: FileURI): Boolean
33+
fun findAllFiles(): List<IFileCollection>
34+
fun getSourceRoots(project: Project): Array<ISourceRoot>
35+
companion object {
36+
val KEY = Key.create<IFileManager>(IFileManager::class.java.name)
37+
fun get(project: Project): IFileManager {
38+
return KEY.get(project)
39+
}
40+
}
41+
}
42+
43+
class FileManager(project: Project) : IFileManager {
44+
private val providers = mutableListOf<IFileScopeProvider>()
45+
46+
init {
47+
addProvider(ConfigurationFileScopeProvider(project))
48+
}
49+
50+
override fun addProvider(provider: IFileScopeProvider) {
51+
providers.add(provider)
52+
}
53+
54+
override fun isInclude(file: File): Boolean {
55+
return isInclude(FileURI.file(file))
56+
}
57+
58+
override fun isInclude(uri: FileURI): Boolean {
59+
return providers.any { it.isInclude(uri) == ThreeState.YES } && !isExclude(uri)
60+
}
61+
62+
override fun isExclude(uri: FileURI): Boolean {
63+
return providers.any { it.isExclude(uri) == ThreeState.YES }
64+
}
65+
66+
override fun findAllFiles(): List<IFileCollection> {
67+
val list = mutableListOf<IFileCollection>()
68+
for (provider in providers) {
69+
val collections = provider.findAllFiles(this)
70+
list.addAll(collections)
71+
}
72+
return list
73+
}
74+
75+
override fun getSourceRoots(project: Project): Array<ISourceRoot> {
76+
val list = mutableListOf<ISourceRoot>()
77+
providers.forEach { list.addAll(it.getSourceRoots(project)) }
78+
return list.toTypedArray()
79+
}
80+
81+
fun collectFiles(file: File, list: MutableList<FileURI>) {
82+
if (file.isFile && isInclude(file)) {
83+
list.add(FileURI.file(file))
84+
} else if (file.isDirectory) {
85+
file.listFiles()?.forEach { collectFiles(it, list) }
86+
}
87+
}
88+
}
89+
90+
class ConfigurationFileScopeProvider(private val project: Project) : IFileScopeProvider {
91+
override fun isInclude(uri: FileURI): ThreeState {
92+
val configurationManager = IConfigurationManager.get(project)
93+
return configurationManager.isInclude(uri)
94+
}
95+
96+
override fun isExclude(uri: FileURI): ThreeState {
97+
val configurationManager = IConfigurationManager.get(project)
98+
return configurationManager.isExclude(uri)
99+
}
100+
101+
override fun findAllFiles(manager: FileManager): List<IFileCollection> {
102+
val configurationManager = IConfigurationManager.get(project)
103+
val collections = mutableListOf<IFileCollection>()
104+
for (source in configurationManager.sourceRoots) {
105+
val dir = source.absoluteDir ?: continue
106+
dir.toFile()?.let { file ->
107+
val files = mutableListOf<FileURI>()
108+
manager.collectFiles(file, files)
109+
collections.add(FileCollection(dir, files))
110+
}
111+
}
112+
return collections
113+
}
114+
115+
override fun getSourceRoots(project: Project): Array<ISourceRoot> {
116+
return IConfigurationManager.get(project).sourceRoots
117+
}
118+
}

EmmyLua-LS/src/main/kotlin/com/tang/intellij/lua/reference/ReferencesSearch.kt renamed to EmmyLua-Common/src/main/ext/com/tang/intellij/lua/reference/ReferencesSearch.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ import com.intellij.psi.PsiElement
44
import com.intellij.psi.PsiFile
55
import com.intellij.psi.PsiNamedElement
66
import com.intellij.psi.PsiReference
7-
import com.intellij.psi.search.GlobalSearchScope
87
import com.intellij.psi.search.SearchScope
98
import com.intellij.util.AbstractQuery
109
import com.intellij.util.Processor
1110
import com.intellij.util.Query
12-
import com.tang.intellij.lua.psi.LuaPsiFile
1311

1412
object ReferencesSearch {
1513
/**
@@ -33,7 +31,7 @@ object ReferencesSearch {
3331
val project = element.project
3432
val pattern = "\\b$name\\b".toRegex()
3533
project.process { file ->
36-
if (scope.contains(file.virtualFile) && file is LuaPsiFile) {
34+
if (scope.contains(file.virtualFile)) {
3735
val text = file.virtualFile.text
3836
if (text != null) {
3937
var matchResult = pattern.find(text)

0 commit comments

Comments
 (0)