|
1 | 1 | package shop.itbug.flutterx.common.yaml |
2 | 2 |
|
3 | 3 | import com.intellij.openapi.application.readAction |
| 4 | +import com.intellij.psi.PsiInvalidElementAccessException |
4 | 5 | import com.intellij.psi.SmartPointerManager |
5 | 6 | import com.intellij.psi.SmartPsiElementPointer |
6 | 7 | import com.intellij.psi.util.PsiTreeUtil |
@@ -71,37 +72,49 @@ data class DartYamlModel( |
71 | 72 |
|
72 | 73 | companion object { |
73 | 74 |
|
74 | | - suspend fun create(element: YAMLKeyValueImpl): DartYamlModel? { |
75 | | - // 在 readAction 内部进行所有 PSI 访问,避免元素在异步操作中失效 |
| 75 | + suspend fun create(elementPointer: SmartPsiElementPointer<YAMLKeyValueImpl>): DartYamlModel? { |
| 76 | + // 1. 获取 project 时也要注意安全性 |
| 77 | + val project = try { elementPointer.project } catch (_: Exception) { return null } |
| 78 | + |
76 | 79 | return readAction { |
77 | | - // 检查元素是否仍然有效 |
78 | | - if (!element.isValid) return@readAction null |
79 | | - val pt = PsiTreeUtil.findChildOfType(element,YAMLPlainTextImpl::class.java) ?: return@readAction null |
80 | | - val hasBlock = PsiTreeUtil.findChildOfType(element,YAMLBlockMappingImpl::class.java) != null |
81 | | - if (hasBlock) return@readAction null |
82 | | - |
83 | | - val version = element.valueText.trim() |
84 | | - if (version.isBlank()) return@readAction null |
85 | | - val name = element.keyText.trim() |
86 | | - val point = SmartPointerManager.getInstance(element.project).createSmartPsiElementPointer(element) |
87 | | - val plainText = SmartPointerManager.getInstance(element.project).createSmartPsiElementPointer(pt) |
88 | | - DartYamlModel( |
89 | | - name, version, tryParseDartVersionType(version), point, plainText, |
90 | | - ) |
| 80 | + try { |
| 81 | + // 2. 检查 element 是否还在 |
| 82 | + val element = elementPointer.element ?: return@readAction null |
| 83 | + if (!element.isValid || project.isDisposed) return@readAction null |
| 84 | + |
| 85 | + // 3. 这里的 pt 指针还是需要的,因为它是 element 的子元素 |
| 86 | + val pt = PsiTreeUtil.findChildOfType(element, YAMLPlainTextImpl::class.java) ?: return@readAction null |
| 87 | + |
| 88 | + // 检查是否有 block (比如有些 pubspec 是 key: { version: 1.0.0 } 这种结构) |
| 89 | + val hasBlock = PsiTreeUtil.findChildOfType(element, YAMLBlockMappingImpl::class.java) != null |
| 90 | + if (hasBlock) return@readAction null |
| 91 | + |
| 92 | + val version = element.valueText.trim() |
| 93 | + if (version.isBlank()) return@readAction null |
| 94 | + val name = element.keyText.trim() |
| 95 | + |
| 96 | + // 创建 pt 的指针 |
| 97 | + val pointerManager = SmartPointerManager.getInstance(project) |
| 98 | + val plainTextPointer = pointerManager.createSmartPsiElementPointer(pt) |
| 99 | + |
| 100 | + // 直接复用传入的 elementPointer,不需要再 create 一次 |
| 101 | + DartYamlModel(name, version, tryParseDartVersionType(version), elementPointer, plainTextPointer) |
| 102 | + } catch (_: PsiInvalidElementAccessException) { |
| 103 | + null |
| 104 | + } |
91 | 105 | } |
92 | 106 | } |
93 | 107 |
|
94 | 108 | /** |
95 | 109 | * 解析model的时候同时请求pub.dev的包数据 |
96 | 110 | * 多了一个请求 |
97 | 111 | */ |
98 | | - suspend fun fetch(element: YAMLKeyValueImpl): DartYamlModel? { |
| 112 | + suspend fun fetch(element: SmartPsiElementPointer<YAMLKeyValueImpl>): DartYamlModel? { |
99 | 113 | val model = create(element) ?: return null |
100 | | - val fileAndProject = readAction { |
101 | | - if (!element.isValid) return@readAction null |
102 | | - element.containingFile to element.project |
| 114 | + val (file, project) = readAction { |
| 115 | + val psi = model.element.element ?: return@readAction null |
| 116 | + psi.containingFile to psi.project |
103 | 117 | } ?: return null |
104 | | - val (file, project) = fileAndProject |
105 | 118 | val isIgnored = YamlFileIgDartPackageCache.getInstance(project).state.hasItem(file, model.name) |
106 | 119 | if (isIgnored) return null |
107 | 120 | val data = PubService.callPluginDetails(model.name) ?: return null |
|
0 commit comments