diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 9329402..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/CHANGELOG.md b/CHANGELOG.md index 98e8def..2b0ce71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,21 @@ ## [Unreleased] +## [1.2.1] - 2023-07-25 + +### Added + +- Support Inline Conditions. + +### Fixed + +- Fix GoFrame ORM unsupported syntax. +- Fix Outdated stub in index Exception. + ## [1.2.0] - 2023-07-15 ### Added + - Support GoFrame ORM. - Support Go ORM Tags Live Template. - Refactor Code Completion. Better Performance! @@ -15,23 +27,29 @@ ## [1.1.0] - 2023-07-04 ### Added + - Assisted code completion with @Table annotation. - Support ORM's table method. ### Fixed + - Fix SQL to Struct error. ## [1.0.2] - 2023-07-04 ### Fixed + - Fix the verify SQL exception. ## [1.0.1] - 2023-07-03 ### Fixed -- Fix the issue where the scanning paths in the settings cannot utilize the delete, move up, move down, and other functions. + +- Fix the issue where the scanning paths in the settings cannot utilize the delete, move up, move down, and other + functions. ### Optimize + - Abstract the core path of the ORM into a common class. - Implement multi-language support, currently supporting Chinese, English, Japanese, and Korean languages. - Separate the plugin description. @@ -39,12 +57,20 @@ ## [1.0.0] - 2023-07-02 ### Added + - ORM Code Completion - SQL to Struct -[Unreleased]: https://github.com/maiqingqiang/go-orm-helper/compare/v1.2.0...HEAD +[Unreleased]: https://github.com/maiqingqiang/go-orm-helper/compare/v1.2.1...HEAD + +[1.2.1]: https://github.com/maiqingqiang/go-orm-helper/compare/v1.2.0...v1.2.1 + [1.2.0]: https://github.com/maiqingqiang/go-orm-helper/compare/v1.1.0...v1.2.0 + [1.1.0]: https://github.com/maiqingqiang/go-orm-helper/compare/v1.0.2...v1.1.0 + [1.0.2]: https://github.com/maiqingqiang/go-orm-helper/compare/v1.0.1...v1.0.2 + [1.0.1]: https://github.com/maiqingqiang/go-orm-helper/compare/v1.0.0...v1.0.1 + [1.0.0]: https://github.com/maiqingqiang/go-orm-helper/tree/v1.0.0 diff --git a/README-ja_JP.md b/README-ja_JP.md index 85925d9..697d842 100644 --- a/README-ja_JP.md +++ b/README-ja_JP.md @@ -38,12 +38,12 @@ ## インストール -### Jetbrains Marketplace からプラグインをインストールする - > 互換性範囲: > - GoLand — 2022.2+ > - IntelliJ IDEA Ultimate — 2022.2+ +### Jetbrains Marketplace からプラグインをインストールする + <a href="https://plugins.jetbrains.com/plugin/22173-go-orm-helper" target="_blank"> <img src="https://blog.johnmai.top/go-orm-helper/assets/installation_button.svg" height="52" alt="Get from Marketplace" title="Get from Marketplace"> </a> diff --git a/README-ko_KR.md b/README-ko_KR.md index e69f232..c1fbc76 100644 --- a/README-ko_KR.md +++ b/README-ko_KR.md @@ -38,12 +38,12 @@ ## 설치 -### Jetbrains Marketplace 에서 플러그인 설치 - > 호환성 범위: > - GoLand — 2022.2+ > - IntelliJ IDEA Ultimate — 2022.2+ +### Jetbrains Marketplace 에서 플러그인 설치 + <a href="https://plugins.jetbrains.com/plugin/22173-go-orm-helper" target="_blank"> <img src="https://blog.johnmai.top/go-orm-helper/assets/installation_button.svg" height="52" alt="Get from Marketplace" title="Get from Marketplace"> </a> diff --git a/README-zh_CN.md b/README-zh_CN.md index 7b1f91b..78e7e50 100644 --- a/README-zh_CN.md +++ b/README-zh_CN.md @@ -34,16 +34,38 @@ ## 使用 +### 代码补全 +https://www.jetbrains.com/help/go/auto-completing-code.html#code-completion-for-functions + ![guide.gif](assets%2Fguide.gif) -## 安装 +### 注解辅助 +有些写法此插件可能无法兼容,导致无法补全。你可以使用 @Model 或者 @Table 解决此问题。 +![annotation.gif](assets%2Fannotation.gif) -### 通过 Jetbrains Marketplace 安装 +插件会扫描项目中所有Struct,建议设置扫描范围。 +![setting.png](assets%2Fsetting.png) + +### 实时模版 +![live-template.gif](assets%2Flive-template.gif) + +### SQL 转 Struct +#### 粘贴方式 +![paste.gif](assets%2Fpaste.gif) + +#### 菜单操作 +选中 SQL -> 点击编辑器右键菜单 -> Go ORM 助手工具箱 -> SQL 转 Struct + +![manual-sql-to-struct.png](assets%2Fmanual-sql-to-struct.png) + +## 安装 > 兼容范围: > - GoLand — 2022.2+ > - IntelliJ IDEA Ultimate — 2022.2+ +### 通过 Jetbrains Marketplace 安装 + <a href="https://plugins.jetbrains.com/plugin/22173-go-orm-helper" target="_blank"> <img src="https://blog.johnmai.top/go-orm-helper/assets/installation_button.svg" height="52" alt="Get from Marketplace" title="Get from Marketplace"> </a> diff --git a/README.md b/README.md index 13f819f..934d162 100644 --- a/README.md +++ b/README.md @@ -32,18 +32,40 @@ for writing ORM code. Supports: Gorm、Xorm、Beego、GoFrame, etc.<br/>⭐️ S - [More Supported](./SUPPORTED.md) ## Usage + +### Code Completion +https://www.jetbrains.com/help/go/auto-completing-code.html#code-completion-for-functions + ![guide.gif](assets%2Fguide.gif) +### Annotation +If the plugin is not compatible with your syntax, you can use the @Model or @Table helper. +![annotation.gif](assets%2Fannotation.gif) + +The plugin will scan the Structs in your project. It is recommended to set the scanning scope. +![setting.png](assets%2Fsetting.png) + +### Live Template +![live-template.gif](assets%2Flive-template.gif) + +### SQL to Struct +#### Paste +![paste.gif](assets%2Fpaste.gif) + +#### Menu Action +Selected SQL -> Editor Popup Menu -> Go ORM Helper Tool -> SQL Convert Struct +![manual-sql-to-struct.png](assets%2Fmanual-sql-to-struct.png) + <!-- Plugin description end --> ## Installation -### Install Plugin from Jetbrains Marketplace - -> Compatibility Range: +> Compatibility Range: > - GoLand — 2022.2+ > - IntelliJ IDEA Ultimate — 2022.2+ +### Install Plugin from Jetbrains Marketplace + <a href="https://plugins.jetbrains.com/plugin/22173-go-orm-helper" target="_blank"> <img src="https://blog.johnmai.top/go-orm-helper/assets/installation_button.svg" height="52" alt="Get from Marketplace" title="Get from Marketplace"> </a> diff --git a/assets/annotation.gif b/assets/annotation.gif new file mode 100644 index 0000000..966b4cd Binary files /dev/null and b/assets/annotation.gif differ diff --git a/assets/live-template.gif b/assets/live-template.gif new file mode 100644 index 0000000..82e6512 Binary files /dev/null and b/assets/live-template.gif differ diff --git a/assets/manual-sql-to-struct.png b/assets/manual-sql-to-struct.png new file mode 100644 index 0000000..d47939f Binary files /dev/null and b/assets/manual-sql-to-struct.png differ diff --git a/assets/paste.gif b/assets/paste.gif new file mode 100644 index 0000000..49e6c4e Binary files /dev/null and b/assets/paste.gif differ diff --git a/assets/setting.png b/assets/setting.png new file mode 100644 index 0000000..caea0d1 Binary files /dev/null and b/assets/setting.png differ diff --git a/example/goframe/main.go b/example/goframe/main.go index 6f96355..87085ae 100644 --- a/example/goframe/main.go +++ b/example/goframe/main.go @@ -12,11 +12,13 @@ type User struct { Age int32 // 年龄 } -func main() { +func test1() (user *User) { g.Model(&User{}).Where("id = ?") -} -func test1() (user *User) { + g.Model(&User{}).Where("id = ? and user_name = ? OR email != ?") + + g.DB().Model(&User{}).Where("id = ? and") + g.Model(&user).Where("id = ?", 1) g.Model(&User{}).Where(g.Map{"user_name": 1, "name": "john"}) diff --git a/example/gorm/main.go b/example/gorm/main.go index 48423af..d278963 100644 --- a/example/gorm/main.go +++ b/example/gorm/main.go @@ -79,3 +79,9 @@ func test6(db *gorm.DB) (user *User) { query.Find(&user) return } + +func test7(db *gorm.DB) (user *User) { + query := db.Where("id = ? and email != ? OR user_name = ?", "") + query.Find(&user) + return +} diff --git a/gradle.properties b/gradle.properties index 0c8606c..ad8ca06 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ pluginGroup = com.github.maiqingqiang.goormhelper pluginName = Go ORM Helper pluginRepositoryUrl = https://github.com/maiqingqiang/go-orm-helper # SemVer format -> https://semver.org -pluginVersion = 1.2.0 +pluginVersion = 1.2.1 # Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html pluginSinceBuild = 222 diff --git a/src/main/java/com/github/maiqingqiang/goormhelper/Types.java b/src/main/java/com/github/maiqingqiang/goormhelper/Types.java index 09c3a8c..982b5c6 100644 --- a/src/main/java/com/github/maiqingqiang/goormhelper/Types.java +++ b/src/main/java/com/github/maiqingqiang/goormhelper/Types.java @@ -13,8 +13,26 @@ public interface Types { List<String> OPERATOR_EXPR = List.of( - "%s = ?", "%s <> ?", "%s != ?", "%s IN ?", "%s LIKE ?", "%s > ?", "%s >= ?", "%s < ?", "%s <= ?", "%s BETWEEN ? AND ?" + "%s = ?", + "%s <> ?", + "%s != ?", + "%s IN ?", + "%s NOT IN ?", + "%s LIKE ?", + "%s > ?", + "%s >= ?", + "%s < ?", + "%s <= ?", + "%s <=> ?", + "%s IS NULL", + "%s IS NOT NULL", + "%s BETWEEN ? AND ?", + "%s NOT BETWEEN ? AND ?" ); + + List<String> LOGICAL_OPERATOR_EXPR = List.of("AND", "OR", "XOR", "NOT"); + List<String> USE_LOGICAL_OPERATOR_SCENE = List.of(" ?", " IS NULL", " IS NOT NULL"); + String MODEL_ANNOTATION = "@Model"; Pattern MODEL_ANNOTATION_PATTERN = Pattern.compile(MODEL_ANNOTATION + "\\((.*?)\\)"); String TABLE_ANNOTATION = "@Table"; diff --git a/src/main/java/com/github/maiqingqiang/goormhelper/codeInsights/completion/GoORMHelperCompletionContributor.java b/src/main/java/com/github/maiqingqiang/goormhelper/codeInsights/completion/GoORMHelperCompletionContributor.java new file mode 100644 index 0000000..fcb7706 --- /dev/null +++ b/src/main/java/com/github/maiqingqiang/goormhelper/codeInsights/completion/GoORMHelperCompletionContributor.java @@ -0,0 +1,29 @@ +package com.github.maiqingqiang.goormhelper.codeInsights.completion; + +import com.github.maiqingqiang.goormhelper.orm.ORMCompletionProvider; +import com.github.maiqingqiang.goormhelper.orm.goframe.codeInsights.completion.GoFrameColumnCompletionProvider; +import com.github.maiqingqiang.goormhelper.orm.gorm.codeInsights.completion.GormColumnCompletionProvider; +import com.github.maiqingqiang.goormhelper.orm.xorm.codeInsights.completion.XormColumnCompletionProvider; +import com.goide.GoParserDefinition; +import com.intellij.codeInsight.completion.CompletionContributor; +import com.intellij.codeInsight.completion.CompletionType; +import com.intellij.patterns.PlatformPatterns; + +import java.util.List; + +public class GoORMHelperCompletionContributor extends CompletionContributor { + + public GoORMHelperCompletionContributor() { + List<ORMCompletionProvider> providers = List.of( + new GormColumnCompletionProvider(), + new XormColumnCompletionProvider(), + new GoFrameColumnCompletionProvider() + ); + + for (ORMCompletionProvider provider : providers) { + extend(CompletionType.BASIC, + PlatformPatterns.psiElement().withElementType(GoParserDefinition.Lazy.STRING_LITERALS), + provider); + } + } +} diff --git a/src/main/java/com/github/maiqingqiang/goormhelper/orm/ORMCompletionProvider.java b/src/main/java/com/github/maiqingqiang/goormhelper/orm/ORMCompletionProvider.java index 99c53b6..669f2b7 100644 --- a/src/main/java/com/github/maiqingqiang/goormhelper/orm/ORMCompletionProvider.java +++ b/src/main/java/com/github/maiqingqiang/goormhelper/orm/ORMCompletionProvider.java @@ -25,6 +25,7 @@ import com.intellij.psi.ResolveState; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ProcessingContext; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,10 +40,9 @@ public abstract class ORMCompletionProvider extends CompletionProvider<Completio private static final Logger LOG = Logger.getInstance(ORMCompletionProvider.class); protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) { - PsiElement currentElement = parameters.getPosition(); - LOG.info("currentElement: " + currentElement.getText()); + LOG.info("currentElement: " + currentElement + " text: " + currentElement.getText()); Project project = currentElement.getProject(); @@ -58,10 +58,43 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull if (!ORMPsiTreeUtil.callHasArgumentAtIndex(goCallExpr, argumentIndex, currentElement.getParent()) && !(currentElement.getParent().getParent() instanceof GoKey)) return; + String prefix = result.getPrefixMatcher().getPrefix(); + int lastSpace = prefix.lastIndexOf(' '); + if (lastSpace >= 0 && lastSpace < prefix.length() - 1) { + String previous = prefix.substring(0, lastSpace); + LOG.info("previous: " + previous + "origin prefix: " + prefix); + + prefix = prefix.substring(lastSpace + 1); + LOG.info("new prefix: " + prefix); + + result = result.withPrefixMatcher(prefix); + + if (Strings.endsWithIgnoreCaseAny(previous, Types.USE_LOGICAL_OPERATOR_SCENE.toArray(new CharSequence[]{}))) { + for (String s : Types.LOGICAL_OPERATOR_EXPR) { + if (StringUtils.containsIgnoreCase(s, prefix)) { + result.addElement(LookupElementBuilder + .create(s) + .withPresentableText(s) + .withIcon(getIcon())); + + String lowerCase = s.toLowerCase(); + + result.addElement(LookupElementBuilder + .create(lowerCase) + .withPresentableText(lowerCase) + .withIcon(getIcon())); + } + } + return; + } + } + GoCompositeElement argument = findTargetGoCompositeElement(currentElement); LOG.info("argument: " + argument); + argument = findAgainArgument(argument); + GoORMHelperCacheManager manager = GoORMHelperCacheManager.getInstance(project); if (argument instanceof GoStatement) { @@ -88,28 +121,9 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull } else if (goUnaryExpr.getExpression() instanceof GoReferenceExpression goReferenceExpression) { if (goReferenceExpression.resolve() instanceof GoVarDefinition goVarDefinition) { GoType goType = goVarDefinition.getGoType(ResolveState.initial()); - - if (goType instanceof GoArrayOrSliceType goArrayOrSliceType) { - goType = goArrayOrSliceType.getType(); - } - - if (goType instanceof GoPointerType goPointerType) { - goType = goPointerType.getType(); - } - handleGoType(parameters, result, descriptor, goType); } else if (goReferenceExpression.resolve() instanceof GoParamDefinition goParamDefinition) { - GoType goType = goParamDefinition.getGoTypeInner(ResolveState.initial()); - - if (goType instanceof GoArrayOrSliceType goArrayOrSliceType) { - goType = goArrayOrSliceType.getType(); - } - - if (goType instanceof GoPointerType goPointerType) { - goType = goPointerType.getType(); - } - handleGoType(parameters, result, descriptor, goType); } } @@ -120,15 +134,6 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull GoType goType = PsiTreeUtil.findChildOfAnyType(goVarDefinition.getParent(), GoType.class); if (goType != null) { - - if (goType instanceof GoArrayOrSliceType goArrayOrSliceType) { - goType = goArrayOrSliceType.getType(); - } - - if (goType instanceof GoPointerType goPointerType) { - goType = goPointerType.getType(); - } - handleGoType(parameters, result, descriptor, goType); } else { GoCompositeLit goCompositeLit = PsiTreeUtil.findChildOfType(goVarDefinition.getParent(), GoCompositeLit.class); @@ -136,17 +141,8 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull handleGoTypeReferenceExpression(parameters, result, descriptor, goCompositeLit.getTypeReferenceExpression()); } } - } else if(goReferenceExpression.resolve() instanceof GoParamDefinition goParamDefinition){ + } else if (goReferenceExpression.resolve() instanceof GoParamDefinition goParamDefinition) { GoType goType = goParamDefinition.getGoTypeInner(ResolveState.initial()); - - if (goType instanceof GoArrayOrSliceType goArrayOrSliceType) { - goType = goArrayOrSliceType.getType(); - } - - if (goType instanceof GoPointerType goPointerType) { - goType = goPointerType.getType(); - } - handleGoType(parameters, result, descriptor, goType); } } else if (argument instanceof GoCompositeLit goCompositeLit) { @@ -155,9 +151,15 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull String schema = manager.getTableStructMapping().get(goStringLiteral.getDecodedText()); handleSchema(parameters, result, project, descriptor, schema); } + } else if (argument instanceof GoType goType) { + handleGoType(parameters, result, descriptor, goType); } } + protected GoCompositeElement findAgainArgument(GoCompositeElement argument) { + return argument; + } + private void handleGoTypeReferenceExpression(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result, GoCallableDescriptor descriptor, GoTypeReferenceExpression expression) { if (expression != null && expression.resolve() instanceof GoTypeSpec goTypeSpec) { scanFields(parameters, descriptor, result, goTypeSpec); @@ -165,8 +167,13 @@ private void handleGoTypeReferenceExpression(@NotNull CompletionParameters param } private void handleGoType(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result, GoCallableDescriptor descriptor, GoType goType) { - if (goType != null && goType.resolve(ResolveState.initial()) instanceof GoTypeSpec goTypeSpec) { - scanFields(parameters, descriptor, result, goTypeSpec); + if (goType != null) { + goType = ORMPsiTreeUtil.getReallyGoType(goType); + + if (goType.resolve(ResolveState.initial()) instanceof GoTypeSpec goTypeSpec) { + scanFields(parameters, descriptor, result, goTypeSpec); + + } } } @@ -241,6 +248,12 @@ private GoCompositeElement findTargetGoCompositeElement(@NotNull PsiElement curr } for (GoCallExpr goCallExpr : PsiTreeUtil.findChildrenOfType(statement, GoCallExpr.class)) { + + GoCompositeElement element = customFindGoCompositeElementByGoCallExpr(goCallExpr); + if (element != null) return element; + + LOG.info("goCallExpr: " + goCallExpr + " text: " + goCallExpr.getText()); + GoCallableDescriptor descriptor = callablesSet.find(goCallExpr, false); if (descriptor == null) continue; @@ -253,6 +266,10 @@ private GoCompositeElement findTargetGoCompositeElement(@NotNull PsiElement curr return null; } + protected GoCompositeElement customFindGoCompositeElementByGoCallExpr(GoCallExpr goCallExpr) { + return null; + } + private @Nullable GoCompositeElement findGoCompositeElement(@NotNull PsiElement currentElement, GoCallableDescriptorSet callablesSet, Map<GoCallableDescriptor, Integer> callables) { if (callables == null || callablesSet == null) return null; @@ -265,6 +282,9 @@ private GoCompositeElement findTargetGoCompositeElement(@NotNull PsiElement curr if (currentStatement instanceof GoAssignmentStatement goAssignmentStatement) { for (GoExpression goExpression : goAssignmentStatement.getLeftHandExprList().getExpressionList()) { + + LOG.info("goExpression: " + goExpression + " text: " + goExpression.getText()); + if (checkAllowTypeByGoPointerType(goExpression.getGoType(ResolveState.initial())) && goExpression.getReference() != null) { PsiElement resolved = goExpression.getReference().resolve(); if (resolved != null) { @@ -362,6 +382,8 @@ private void scanFields(@NotNull CompletionParameters parameters, GoCallableDesc comment = GoDocumentationProvider.getCommentText(GoDocumentationProvider.getCommentsForElement(field), false); } + if (column != null && !column.contains(result.getPrefixMatcher().getPrefix())) continue; + addElement(result, column, comment, type, goTypeSpec); if (!(parameters.getPosition().getParent().getParent() instanceof GoKey)) { diff --git a/src/main/java/com/github/maiqingqiang/goormhelper/orm/goframe/GoFrameTypes.java b/src/main/java/com/github/maiqingqiang/goormhelper/orm/goframe/GoFrameTypes.java index 0f558be..9d4c650 100644 --- a/src/main/java/com/github/maiqingqiang/goormhelper/orm/goframe/GoFrameTypes.java +++ b/src/main/java/com/github/maiqingqiang/goormhelper/orm/goframe/GoFrameTypes.java @@ -1,5 +1,6 @@ package com.github.maiqingqiang.goormhelper.orm.goframe; +import com.github.maiqingqiang.goormhelper.Types; import com.github.maiqingqiang.goormhelper.inspections.GoTypeSpecDescriptor; import com.goide.inspections.core.GoCallableDescriptor; import com.goide.inspections.core.GoCallableDescriptorSet; @@ -90,35 +91,37 @@ public interface GoFrameTypes { Map<GoCallableDescriptor, Integer> SCHEMA_CALLABLES = Map.ofEntries( - Map.entry(GoFunctionDescriptor.of("github.com/gogf/gf/frame/g.Model"), 0) + Map.entry(GoFunctionDescriptor.of("github.com/gogf/gf/frame/g.Model"), 0), + Map.entry(GoMethodDescriptor.of("(github.com/gogf/gf/database/gdb.DB).Model"), 0) ); - GoCallableDescriptorSet SCHEMA_CALLABLES_SET = new GoCallableDescriptorSet(SCHEMA_CALLABLES.keySet()); - - - Map<GoCallableDescriptor, Integer> OTHER_SCHEMA_CALLABLES = Map.ofEntries(); + List<String> OTHER_SCHEMA_CALLABLES = List.of( + "Ctx", + "Table" + ); - GoCallableDescriptorSet OTHER_CALLABLES_SET = new GoCallableDescriptorSet(OTHER_SCHEMA_CALLABLES.keySet()); + List<String> ALLOW_FIELDS = List.of( + "columns" + ); - List<String> OPERATOR_EXPR = List.of( - "%s = ?", "%s <> ?", "%s IN ?", "%s LIKE ?", "%s > ?", "%s BETWEEN ? AND ?"); + GoCallableDescriptorSet SCHEMA_CALLABLES_SET = new GoCallableDescriptorSet(SCHEMA_CALLABLES.keySet()); Map<GoCallableDescriptor, List<String>> QUERY_EXPR = Map.ofEntries( - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Where"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Wheref"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).WhereOr"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).All"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).One"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Array"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Value"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Count"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindAll"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindOne"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindArray"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindValue"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindCount"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindScan"), OPERATOR_EXPR), - Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Having"), OPERATOR_EXPR) + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Where"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Wheref"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).WhereOr"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).All"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).One"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Array"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Value"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Count"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindAll"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindOne"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindArray"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindValue"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindCount"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).FindScan"), Types.OPERATOR_EXPR), + Map.entry(GoMethodDescriptor.of("(*github.com/gogf/gf/database/gdb.Model).Having"), Types.OPERATOR_EXPR) ); Set<GoCallableDescriptor> ALLOW_TYPES = Set.of( diff --git a/src/main/java/com/github/maiqingqiang/goormhelper/orm/goframe/codeInsights/completion/GoFrameColumnCompletionProvider.java b/src/main/java/com/github/maiqingqiang/goormhelper/orm/goframe/codeInsights/completion/GoFrameColumnCompletionProvider.java index b19ac78..7ed3fb9 100644 --- a/src/main/java/com/github/maiqingqiang/goormhelper/orm/goframe/codeInsights/completion/GoFrameColumnCompletionProvider.java +++ b/src/main/java/com/github/maiqingqiang/goormhelper/orm/goframe/codeInsights/completion/GoFrameColumnCompletionProvider.java @@ -6,11 +6,10 @@ import com.github.maiqingqiang.goormhelper.ui.Icons; import com.goide.inspections.core.GoCallableDescriptor; import com.goide.inspections.core.GoCallableDescriptorSet; -import com.goide.psi.GoFieldDeclaration; -import com.goide.psi.GoTag; -import com.goide.psi.GoType; -import com.goide.psi.GoTypeSpec; +import com.goide.psi.*; +import com.goide.psi.impl.GoPsiUtil; import com.intellij.psi.ResolveState; +import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -107,4 +106,53 @@ protected boolean checkGoFieldDeclaration(GoFieldDeclaration field) { return !descriptor.equals(GoFrameTypes.G_META) && !descriptor.equals(GoFrameTypes.GMETA_META); } + + @Override + protected GoCompositeElement customFindGoCompositeElementByGoCallExpr(GoCallExpr goCallExpr) { + return findGoTypeByReceiver(goCallExpr, allowTypes()); + } + + private @Nullable GoType findGoTypeByReceiver(GoCallExpr goCallExpr, Set<GoCallableDescriptor> allowTypes) { + GoReferenceExpression callRef = GoPsiUtil.getCallReference(goCallExpr); + String refName = callRef != null ? callRef.getIdentifier().getText() : null; + + if (callRef != null && GoFrameTypes.OTHER_SCHEMA_CALLABLES.contains(refName)) { + GoMethodDeclaration declaration = ObjectUtils.tryCast(callRef.resolve(), GoMethodDeclaration.class); + if (declaration != null) { + GoType resultType = declaration.getResultType(); + + if (resultType instanceof GoPointerType goPointerType) { + resultType = goPointerType.getType(); + } + + if (resultType != null && resultType.resolve(ResolveState.initial()) instanceof GoTypeSpec goTypeSpec) { + GoTypeSpecDescriptor descriptor = GoTypeSpecDescriptor.of(goTypeSpec, resultType, true); + + if (allowTypes != null && allowTypes.contains(descriptor) && declaration.getReceiver() != null && declaration.getReceiver().getType() instanceof GoPointerType goPointerType) { + GoType goType = goPointerType.getType(); + if (goType != null && goType.resolve(ResolveState.initial()) instanceof GoTypeSpec spec && + spec.getSpecType().getType() instanceof GoStructType goStructType) { + + for (GoFieldDeclaration field : goStructType.getFieldDeclarationList()) { + if (GoFrameTypes.ALLOW_FIELDS.contains(field.getFieldDefinitionList().get(0).getName()) && field.getType() != null) { + return field.getType(); + } + } + } + } + } + } + } + return null; + } + + @Override + protected GoCompositeElement findAgainArgument(GoCompositeElement argument) { + if (argument instanceof GoCallExpr goCallExpr) { + GoType newArgument = findGoTypeByReceiver(goCallExpr, Set.of(GoTypeSpecDescriptor.of("builtin.string"))); + if (newArgument != null) return newArgument; + } + return argument; + } + } diff --git a/src/main/java/com/github/maiqingqiang/goormhelper/orm/gorm/codeInsights/completion/GormCompletionContributor.java b/src/main/java/com/github/maiqingqiang/goormhelper/orm/gorm/codeInsights/completion/GormCompletionContributor.java index a1e4875..89e5087 100644 --- a/src/main/java/com/github/maiqingqiang/goormhelper/orm/gorm/codeInsights/completion/GormCompletionContributor.java +++ b/src/main/java/com/github/maiqingqiang/goormhelper/orm/gorm/codeInsights/completion/GormCompletionContributor.java @@ -1,14 +1,17 @@ package com.github.maiqingqiang.goormhelper.orm.gorm.codeInsights.completion; import com.goide.GoParserDefinition; +import com.goide.psi.GoFile; import com.intellij.codeInsight.completion.CompletionContributor; import com.intellij.codeInsight.completion.CompletionType; import com.intellij.patterns.PlatformPatterns; +import com.intellij.patterns.StandardPatterns; public class GormCompletionContributor extends CompletionContributor { public GormCompletionContributor() { extend(CompletionType.BASIC, PlatformPatterns.psiElement() - .withElementType(GoParserDefinition.Lazy.STRING_LITERALS), + .withElementType(GoParserDefinition.Lazy.STRING_LITERALS) + .inFile(StandardPatterns.instanceOf(GoFile.class)), new GormColumnCompletionProvider()); } } diff --git a/src/main/java/com/github/maiqingqiang/goormhelper/services/GoORMHelperCacheManager.java b/src/main/java/com/github/maiqingqiang/goormhelper/services/GoORMHelperCacheManager.java index b3aee37..d4af015 100644 --- a/src/main/java/com/github/maiqingqiang/goormhelper/services/GoORMHelperCacheManager.java +++ b/src/main/java/com/github/maiqingqiang/goormhelper/services/GoORMHelperCacheManager.java @@ -97,7 +97,8 @@ public void scanProject(@NotNull VirtualFile virtualFile) { public void scanProject(@NotNull VirtualFile virtualFile, List<String> excluded) { for (VirtualFile file : virtualFile.getChildren()) { - if (!file.isValid() || (excluded != null && excluded.contains(file.getName()))) continue; + if (!file.isValid() || (excluded != null && excluded.contains(file.getName())) || file.getName().startsWith(".")) + continue; if (file.isDirectory()) { scanProject(file, excluded); @@ -113,14 +114,16 @@ public void scanProject(@NotNull VirtualFile virtualFile, List<String> excluded) public void parseGoFile(@NotNull VirtualFile file) { if (!(file.isValid() && file.getName().endsWith('.' + GoFileType.DEFAULT_EXTENSION))) return; - DumbService.getInstance(project).runWhenSmart(() -> { + DumbService.getInstance(project).runReadActionInSmartMode(() -> { Document document = FileDocumentManager.getInstance().getDocument(file); if (document != null && PsiManager.getInstance(project).findFile(file) instanceof GoFile goFile) { List<String> structList = new ArrayList<>(); - for (GoTypeSpec typeSpec : goFile.getTypes()) { + Collection<GoTypeSpec> goTypeSpecCollection = PsiTreeUtil.findChildrenOfType(goFile, GoTypeSpec.class); + + for (GoTypeSpec typeSpec : goTypeSpecCollection) { String structName = typeSpec.getName(); if (!(typeSpec.getSpecType().getType() instanceof GoStructType && structName != null)) continue; diff --git a/src/main/java/com/github/maiqingqiang/goormhelper/utils/ORMPsiTreeUtil.java b/src/main/java/com/github/maiqingqiang/goormhelper/utils/ORMPsiTreeUtil.java index 3fd98ab..648be63 100644 --- a/src/main/java/com/github/maiqingqiang/goormhelper/utils/ORMPsiTreeUtil.java +++ b/src/main/java/com/github/maiqingqiang/goormhelper/utils/ORMPsiTreeUtil.java @@ -1,6 +1,9 @@ package com.github.maiqingqiang.goormhelper.utils; +import com.goide.psi.GoArrayOrSliceType; import com.goide.psi.GoCallExpr; +import com.goide.psi.GoPointerType; +import com.goide.psi.GoType; import com.goide.psi.impl.GoPsiUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; @@ -23,4 +26,16 @@ public static boolean callHasArgumentAtIndex(@NotNull GoCallExpr call, int argum argument = GoPsiUtil.skipParens(argument); return argument == ContainerUtil.getOrElse(call.getArgumentList().getExpressionList(), argumentIndex, (Object) null); } + + public static GoType getReallyGoType(GoType goType) { + if (goType instanceof GoArrayOrSliceType goArrayOrSliceType) { + goType = goArrayOrSliceType.getType(); + } + + if (goType instanceof GoPointerType goPointerType) { + goType = goPointerType.getType(); + } + + return goType; + } } diff --git a/src/main/java/com/github/maiqingqiang/goormhelper/utils/Strings.java b/src/main/java/com/github/maiqingqiang/goormhelper/utils/Strings.java index 7cad84a..3480441 100644 --- a/src/main/java/com/github/maiqingqiang/goormhelper/utils/Strings.java +++ b/src/main/java/com/github/maiqingqiang/goormhelper/utils/Strings.java @@ -1,5 +1,8 @@ package com.github.maiqingqiang.goormhelper.utils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; + import java.util.Map; public class Strings { @@ -66,4 +69,14 @@ public static String clearSingleQuotn(String s) { return s; } + public static boolean endsWithIgnoreCaseAny(CharSequence sequence, CharSequence... searchStrings) { + if (!StringUtils.isEmpty(sequence) && !ArrayUtils.isEmpty(searchStrings)) { + for (CharSequence searchString : searchStrings) { + if (StringUtils.endsWithIgnoreCase(sequence, searchString)) { + return true; + } + } + } + return false; + } } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index e5e705a..99e15b3 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -5,30 +5,19 @@ <vendor>John Mai</vendor> <depends>com.intellij.modules.platform</depends> - <!-- <depends>com.intellij.modules.go</depends>--> <depends>org.jetbrains.plugins.go</depends> <resource-bundle>messages.GoORMHelperBundle</resource-bundle> <extensions defaultExtensionNs="com.intellij"> - - <!-- <liveTemplateContext implementation="com.github.maiqingqiang.goormhelper.codeInsights.template.GoORMTemplateContextType"/>--> - <!-- <liveTemplateContext implementation="com.goide.editor.template.GoLiveTemplateContextType$Tag"/>--> <defaultLiveTemplates file="liveTemplates/Go ORM Tags.xml"/> - <projectService serviceImplementation="com.github.maiqingqiang.goormhelper.services.GoORMHelperCacheManager"/> <projectService serviceImplementation="com.github.maiqingqiang.goormhelper.services.GoORMHelperProjectSettings"/> <completion.contributor language="go" - implementationClass="com.github.maiqingqiang.goormhelper.orm.gorm.codeInsights.completion.GormCompletionContributor"/> - - <completion.contributor language="go" - implementationClass="com.github.maiqingqiang.goormhelper.orm.xorm.codeInsights.completion.XormCompletionContributor"/> - - <completion.contributor language="go" - implementationClass="com.github.maiqingqiang.goormhelper.orm.goframe.codeInsights.completion.GoFrameCompletionContributor"/> + implementationClass="com.github.maiqingqiang.goormhelper.codeInsights.completion.GoORMHelperCompletionContributor"/> <highlightVisitor implementation="com.github.maiqingqiang.goormhelper.codeInsights.daemon.GoORMHelperHighlightVisitor"/> @@ -39,12 +28,8 @@ <projectConfigurable parentId="tools" - instance="com.github.maiqingqiang.goormhelper.ui.SettingConfigurable" - displayName="Go ORM Helper"/> - </extensions> - - <extensions defaultExtensionNs="com.goide"> - + key="name" + instance="com.github.maiqingqiang.goormhelper.ui.SettingConfigurable"/> </extensions> <projectListeners> diff --git a/src/main/resources/messages/GoORMHelperBundle_zh.properties b/src/main/resources/messages/GoORMHelperBundle_zh.properties index 85e6d5e..d992866 100644 --- a/src/main/resources/messages/GoORMHelperBundle_zh.properties +++ b/src/main/resources/messages/GoORMHelperBundle_zh.properties @@ -1,6 +1,6 @@ name=Go ORM \u52A9\u624B # actions -group.GoORMHelper.EditorPopupMenu.text=Go ORM Helper \u5DE5\u5177\u7BB1 +group.GoORMHelper.EditorPopupMenu.text=Go ORM \u52A9\u624B\u5DE5\u5177\u7BB1 # intializing initializing.title=\u521D\u59CB\u5316 Go ORM \u52A9\u624B # convert struct