diff --git a/.claude/guidelines/TEST_CASE_GUIDELINE.md b/.claude/guidelines/TEST_CASE_GUIDELINE.md index 131a536b..fb6ba2f7 100644 --- a/.claude/guidelines/TEST_CASE_GUIDELINE.md +++ b/.claude/guidelines/TEST_CASE_GUIDELINE.md @@ -1,47 +1,155 @@ # Test Case Implementation Guidelines Follow the rules below when implementing test code. -## Code Inspection Functionality -Implement tests for code inspection functionality using the following steps: +## Common Test Case Implementation +- For individual test data, call `addSqlFile()` from `@src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt` within each test case method separately. This prevents unrelated test data from being registered in other test cases. +- For DAO class test data, use `addDaoJavaFile()` from `@src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt`. +- For Entity test data, use `addEntityJavaFile()` from `@src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt`. +- The default source directory for the virtual test project is `src/java/doma/example`. If you need to register files under a different package name, use `addOtherPackageJavaFile()` or `addOtherPackageSqlFile()`. +- To retrieve information about SQL files registered in the virtual test project, use `findSqlFile()` from `@src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt`. +- To retrieve information about DAO classes registered in the virtual test project, use `findDaoClass()` from `@src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt`. +- If you need to register classes other than DAO or Entity classes, such as subclasses of ExpressionFunction or domain classes, use `addOtherJavaFile()` from `@src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt`. -## Implementation of Test Case Classes +## Code Inspection Feature Test Case Implementation +### Description +- Implement tests for code inspection functionality using the following steps. + +### Test Case Implementation - Implement test case classes in `@src/test/kotlin/org/domaframework/doma/intellij/inspection`. - Implement test cases for each subclass of **AbstractBaseJavaLocalInspectionTool**. - Name the test case class as `InspectionTest`. -- The test case class should extend `DomaSqlTest`. +- The test case class should extend `@src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt`. - Override **setUp()** to add mock **Entity** classes or other necessary components to the virtual project for testing. - Register the target **AbstractBaseJavaLocalInspectionTool** subclass using **myFixture.enableInspections**. - In test case functions, retrieve the target Dao class using **DomaSqlTest#findDaoClass()** and test the highlighting results using **myFixture.testHighlighting()**. +- Create the target Dao class or SQL file for inspection. +- Wrap the elements to be error-highlighted with the **** tag and specify the error message to be displayed using the **descr** option. -### Implementation of Test Cases -Create the target Dao class or SQL file for inspection. -Wrap the elements to be error-highlighted with the **** tag and specify the error message to be displayed using the **descr** option. - -**Test Data for Dao Classes** +### Test Data - Implement test data Dao classes in **Java**. - Annotate test data Dao classes with **@Dao**. - Place them under the appropriate subpackage in `@src/test/testData/src/main/java/doma/example/dao/inspection`. - Implement any other necessary classes as needed. +- When creating test cases, prepare and verify the following Entity classes to test parent-child relationships: + - Parent class annotated with @Entity + - Subclass without @Entity annotation + - Subclass annotated with @Entity +- Using the above, create the following test cases for features that use `PsiClass`: + - Test cases using fields/methods defined in parent classes + - Test cases using fields/methods defined in subclasses +- Examples: + - Test that bind variable definition inspection doesn't highlight errors when using fields defined in parent classes + - Test that include/exclude option checking in DAO method annotations doesn't highlight errors when using fields defined in parent classes + - Test that code completion shows fields/methods defined in parent classes as completion candidates +- Create and place SQL files in a directory named after the corresponding Dao class under `@src/test/testData/src/main/resources/META-INF/doma/example/dao`. +- When creating test cases for bind variables, prepare test data that checks instance field methods, static field methods, field methods of elements defined in loop directives, custom functions, and built-in functions. For cases combining multiple variables, ensure comprehensive coverage of all variable combination patterns. -**Entity Test Data** -When creating test cases, prepare and verify the following Entity classes to test parent-child relationships: -- Parent class annotated with @Entity -- Subclass without @Entity annotation -- Subclass annotated with @Entity +## Action Feature Test Case Implementation +### Description +- Action feature test cases should be implemented as subclasses of `DomaSqlTest`. -Using the above, create the following test cases for features that use `PsiClass`: -- Test cases using fields/methods defined in parent classes -- Test cases using fields/methods defined in subclasses +### Test Case Implementation +- Implement test case methods that verify both the visibility of the action in the menu and the state of the system after the action is executed. -**Examples** -- Test that bind variable definition inspection doesn't highlight errors when using fields defined in parent classes -- Test that include/exclude option checking in DAO method annotations doesn't highlight errors when using fields defined in parent classes -- Test that code completion shows fields/methods defined in parent classes as completion candidates +### Test Data +- Prepare the necessary DAO classes and SQL files as test data. Specify the action invocation location by placing a `` marker in the file where the action will be executed. -#### Test Data for SQL Files -- Create and place SQL files in a directory named after the corresponding Dao class under `@src/test/testData/src/main/resources/META-INF/doma/example/dao`. -- When creating test cases for bind variables, prepare test data that checks instance field methods, static field methods, field methods of elements defined in loop directives, custom functions, and built-in functions. - For cases combining multiple variables, ensure comprehensive coverage of all variable combination patterns. +## Intention Action Feature Test Case Implementation +### Description +- Intention action test cases should be implemented as subclasses of `DomaSqlTest`. +- Implement test case methods that verify both the visibility/non-visibility of the intention action menu and the state after executing the action. +- For menu display tests, check for the existence of a menu item whose family name matches the expected value in the list of actions displayed in the menu. +- After executing the action with `myFixture.launchAction()`, use `myFixture.checkResultByFile()` to compare the file contents after the action with the expected result file. +- For the "Convert SQL file to @Sql annotation" action, test that it can be invoked both from the DAO method and from the SQL file. + +### Test Data +- Prepare the necessary DAO classes and SQL files as test data. +- Place a `` marker at the location where you want to invoke the action. +- As with formatter tests, prepare an expected result file to compare the file contents after the action is executed. + +## Line Marker Feature Test Case Implementation +### Description +- Line marker test cases should be implemented as subclasses of `DomaSqlTest`. + +### Test Case Implementation +- Implement test case methods that verify the visibility of gutter icons, the number of gutter icons displayed for a file, and the behavior when a gutter icon is clicked. + +### Test Data +- Prepare the necessary DAO classes and SQL files as test data. +- For verifying the behavior when a gutter icon is clicked, use the first displayed gutter icon found in the test as the target for the action. + +## Code Completion Feature Test Case Implementation +### Description +- Code completion test cases should be implemented as subclasses of `DomaSqlTest`. + +### Test Case Implementation +- Implement test case methods that check the contents of the suggestion list (completion suggestions). +- Verify that expected words appear in the suggestions and that unexpected words do not appear. + +### Test Data +- Prepare the necessary DAO classes and SQL files as test data. +- Place a `` marker at the position where code completion should be invoked, and evaluate both the list of expected suggestions and the list of suggestions that should not be shown. + +## Reference Resolution Feature Test Case Implementation +### Description +- Reference resolution test cases should be implemented as subclasses of `DomaSqlTest`. + +### Test Case Implementation +- Implement test case methods that verify the combination of the source class and the element text for elements inside bind variables. +- For method reference resolution, also check the combination of argument types to ensure that the correct resolution is performed. + +### Test Data +- Prepare the necessary DAO classes and SQL files as test data. +- Map the list of target element texts for reference resolution to the information of the source class (and argument types for methods) obtained by resolution, and verify that the actual reference resolution results match the expected mapping. +- Since the same element text may resolve to multiple definitions, the mapping between element text and source class information should be one-to-many. +- For literals or elements that do not have a reference, set the expected value to null. + +## Documentation Feature Test Case Implementation +### Description +- Documentation test cases should be implemented as subclasses of `DomaSqlTest`. + +### Test Case Implementation +- Implement test case methods that prepare the expected documentation information in HTML format for elements inside bind variables, and compare it with the actual displayed text. + +### Test Data +- Prepare the necessary DAO classes and SQL files as test data. +- Place a `` marker at the position of the element for which you want to reference the documentation information. +- In the expected HTML text, describe the class path using `` tags. If the element has a type, describe the tags for each nested type. After the tag representing the type information, write the target element text. + +## Refactoring Feature Test Case Implementation +### Description +- Refactoring test cases should be implemented as subclasses of `DomaSqlTest`. +- The refactoring feature includes renaming DAO method names and DAO class names. However, since creating test data for class renaming is difficult, only test cases for DAO method renaming are implemented. +- Prepare both the expected data before and after renaming, and implement test case methods that compare the state before and after renaming. Also, verify that the SQL file before renaming does not remain after the operation. + +### Test Case Implementation +- Place a `` marker at the method name you want to rename, and after executing the rename, check that the method name and the associated SQL file name have been renamed accordingly. + +### Test Data +- Prepare the necessary DAO classes and SQL files as test data. + +## Formatter Feature Test Case Implementation +### Description +- Formatter test cases should be implemented as subclasses of `BasePlatformTestCase`. +- The test compares the test data with the expected value data to verify that the formatting process produces the expected result. +- The execution of the formatting and the comparison with the expected value data are implemented by `formatSqlFile()` in #file:SqlFormatTest.kt. + +### Test Case Implementation +- Prepare both a pre-format file and an expected value file for each test case. +- The expected value file should be named `[test data file name]_format.sql` so that the test data and expected value data are displayed together in the project tab. + +### Test Data +- Test data files do not need to be registered in the virtual project. Place them under `src/test/testData/sql/formatter`. + +## Parser Feature Test Case Implementation +### Description +- Parser test cases should be implemented as subclasses of `ParsingTestCase`. +- Prepare the expected PSI tree structure data, and ensure that the test case method name matches the corresponding file name. +- By calling `doTest()`, the standard parser test provided by the framework will be executed. + +### Test Case Implementation +- Obtain the expected PSI tree data by copying the tree information displayed in IntelliJ's debug environment via "Tools > View PSI Structure". +- To capture all differences, including spaces, make sure to check "Show PsiWhiteSpace" before copying the tree information as text. -### Reference -For actual implementation examples using Doma, refer to the [Doma GitHub repository](https://github.com/domaframework/doma/tree/master/integration-test-java/src/main/java/org/seasar/doma/it/dao). +## Reference +- For actual implementation examples using Doma, refer to the [Doma GitHub repository](https://github.com/domaframework/doma/tree/master/integration-test-java/src/main/java/org/seasar/doma/it/dao). diff --git a/CLAUDE.md b/CLAUDE.md index b59105a3..96c581ba 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,7 +15,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ./gradlew test # Run single test class -./gradlew test --tests "org.domaframework.doma.intellij.formatter.SqlFormatterTest" +./gradlew check # Code formatting and linting ./gradlew spotlessApply @@ -107,7 +107,7 @@ Feature Package └── AnAction subclass ``` -### Common +## Common **Accessing `PsiClass` Members** When retrieving fields and methods from `PsiClass`, use `allFields` and `allMethods` instead of `fields` and `methods`. @@ -120,6 +120,8 @@ to achieve equivalent functionality with `findField()` and `findMethod()`. Each feature requires implementing corresponding classes following the IntelliJ platform conventions. Complex logic should not be implemented directly in these corresponding classes but delegated to separate classes (Processors or Handlers). +## Main Classes of Each Feature + ### Actions Action functionality for navigating between DAO files and SQL files @@ -130,7 +132,7 @@ Action functionality for navigating between DAO files and SQL files Class names should have `Action` as a suffix. Classes should not have properties; necessary information should be obtained within functions. -#### Intention Actions for SQL/Annotation Conversion +### Intention Actions for SQL/Annotation Conversion **ConvertSqlFileToAnnotationAction**: Converts SQL file content to @Sql annotation - Extends `PsiElementBaseIntentionAction` for context-sensitive availability @@ -167,22 +169,30 @@ Code inspection functionality for DAO methods and DOMA directives in SQL - **[Feature Package](src/main/kotlin/org/domaframework/doma/intellij/inspection)** - **Main Classes**: `InspectionTool` - Code inspection class for DAO: `AbstractBaseJavaLocalInspectionTool` subclasses + - **DaoAnnotationOptionParameterInspection**: DAOメソッドに付与されたアノテーションオプション(include/exclude)にEntityクラスで定義されたフィールドが指定されていることを検査 + - **DaoAnnotationReturnTypeInspection**: DAOメソッドの戻り値が適切であることを検査 + - **DaoMethodParamTypeInspection**: DAOメソッドのパラメータが適切であることを検査 + - **SqlFileExistInspection**: DAOメソッドに対応するSQLファイルが存在することを検査 + - **UsedDaoMethodParamInspection**: DAOメソッドのパラメータがSQLファイル内で使用されていることを検査 - Code inspection class for SQL: `LocalInspectionTool` subclasses + - **SqlBindVariableInspection**: バインド変数内の要素定義元を検査 + - **SqlFunctionCallInspection**: カスタム関数、組み込み関数の定義元を検査 + - **SqlLoopDirectiveTypeInspection**: ループディレクティブで指定されている変数の型を検査 + - **SqlTestDataInspection**: ディレクティブの後ろにテストデータが存在していることを検査 - **Class Naming Rules**: Use `Inspection` as a suffix -- **Related Classes** - - Processor: Classes that check inspection target elements. Provides common check processing for inspection targets that meet specific conditions - - **Class Naming Rules**: Use `Checker` or `Processor` as a suffix depending on the purpose - - Provider: Provider that returns a list of `InspectionTool` subclasses - - **Class Naming Rules**: Use `Provider` as a suffix - - Visitor: Classes that search for inspection target elements. Called from `InspectionTool` - - **Class Naming Rules**: Have the same name as the calling `InspectionTool` with `Visitor` as a suffix - - QuickFix: Classes that provide fix actions for inspection results - - Consists of a `Factory` object that provides quick fix objects and the main `QuickFix` object - - **Class Naming Rules** - - `Factory` object: Use `QuickFixFactory` as a suffix - - `QuickFix` object: Use `QuickFix` as a suffix - - [ValidationResult](src/main/kotlin/org/domaframework/doma/intellij/common/validation/result): Classes that provide error messages and highlights for code inspection results - - **Class Naming Rules**: Use `ValidationResult` as a suffix. Name classes according to the message resources to be displayed +- Processor: Classes that check inspection target elements. Provides common check processing for inspection targets that meet specific conditions + - **Class Naming Rules**: Use `Checker` or `Processor` as a suffix depending on the purpose +- Provider: Provider that returns a list of `InspectionTool` subclasses + - **Class Naming Rules**: Use `Provider` as a suffix +- Visitor: Classes that search for inspection target elements. Called from `InspectionTool` + - **Class Naming Rules**: Have the same name as the calling `InspectionTool` with `Visitor` as a suffix +- QuickFix: Classes that provide fix actions for inspection results + - Consists of a `Factory` object that provides quick fix objects and the main `QuickFix` object + - **Class Naming Rules** + - `Factory` object: Use `QuickFixFactory` as a suffix + - `QuickFix` object: Use `QuickFix` as a suffix +- [ValidationResult](src/main/kotlin/org/domaframework/doma/intellij/common/validation/result): Classes that provide error messages and highlights for code inspection results + - **Class Naming Rules**: Use `ValidationResult` as a suffix. Name classes according to the message resources to be displayed **Coding Rule** For code inspection features, always implement `InspectionTool` and `Visitor` as separate classes. @@ -191,14 +201,82 @@ When the logic within `Visitor` becomes complex, implement separate Processor cl ### Completion Code completion functionality for DOMA directive syntax in SQL - **[Feature Package](src/main/kotlin/org/domaframework/doma/intellij/contributor/sql)** -- **Related Classes** - - CompletionContributor: Entry point for code completion - - **Class Naming Rules**: Use `CompletionContributor` as a suffix - - Provider: Classes that provide completion candidates in specific contexts - - **Class Naming Rules**: Use `CompletionProvider` as a suffix - - Processor: Classes that filter and transform completion candidates - - **Class Naming Rules**: Use `Processor` as a suffix - - [Handler](src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive): Classes that generate suggestion candidates for each directive type - - **Class Naming Rules**: Use `Handler` as a suffix - - [Collector](src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/collector): Classes that collect directive suggestion candidates. Called from `Handler` - - **Class Naming Rules**: Use `Collector` as a suffix +- CompletionContributor: Entry point for code completion + - **Class Naming Rules**: Use `CompletionContributor` as a suffix +- Provider: Classes that provide completion candidates in specific contexts + - **Class Naming Rules**: Use `CompletionProvider` as a suffix +- Processor: Classes that filter and transform completion candidates + - **Class Naming Rules**: Use `Processor` as a suffix +- [Handler](src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive): Classes that generate suggestion candidates for each directive type + - **Class Naming Rules**: Use `Handler` as a suffix +- [Collector](src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/collector): Classes that collect directive suggestion candidates. Called from `Handler` + - **Class Naming Rules**: Use `Collector` as a suffix + +### Refactoring +Functionality for renaming SQL files and directories when DAO classes or methods are renamed. +- **Feature Package**: `src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao` +- **Processor (Rename Processor Classes)** + - **DaoMethodRenameProcessor**: Detects renaming of DAO method names and renames the corresponding SQL file. + - **DaoPackageRenameListenerProcessor**: Detects renaming of DAO class package names and renames the corresponding SQL directory. Implemented as a subclass of `RefactoringElementListenerProvider` to support changes from the project view. + - **DaoRenameProcessor**: Detects renaming of DAO class names and renames the corresponding SQL directory. + - **Class Naming Rules**: Use the `Processor` suffix. + - Use `canProcessElement()` to determine if the element is a rename target, and `renameElement()` to perform the rename. Since the original rename process is not executed, always call `super.renameElement()` at the end. + +### Reference Resolution +Functionality for resolving references to the definition of elements inside Doma bind variables in SQL. +- **Feature Package**: `src/main/kotlin/org/domaframework/doma/intellij/reference` +- **Contributor**: Registers reference resolution extension points in IntelliJ. + - **Class Naming Rules**: Use the `ReferenceContributor` suffix. +- **Provider**: Selects elements for reference resolution and delegates to the appropriate reference class. + - **Class Naming Rules**: Use the `ReferenceProvider` suffix. + - Bind variables may have parent-child relationships such as `SqlElFieldAccessExpr` > `SqlElIdExpr`. Resolution is performed from the smallest granularity upward for the most precise result. +- **Reference**: Performs the actual reference resolution. Implemented as subclasses of `SqlElExprReference` (which extends `PsiReferenceBase`). + - **SqlElClassExprReference**: Resolves fully qualified class names in static field access elements. + - **SqlElIdExprReference**: Resolves the smallest unit of bind variable elements (DAO parameters, fields, etc.). + - **SqlElForDirectiveIdExprReference**: Resolves elements defined within loop directives. + - **SqlElFunctionCallExprReference**: Resolves custom and built-in function references. + - **SqlElStaticFieldReference**: Resolves the top-level static field or method in static field access. + - **Class Naming Rules**: Use the `Reference` suffix. +- **Manipulator**: Supports renaming of reference target elements. Used to determine the reference range when the element text is changed. + - **Class Naming Rules**: Use the `Manipulator` suffix. + +### Documentation +Functionality for displaying documentation for the definition of elements inside Doma bind variables in SQL. +- **Feature Package**: `src/main/kotlin/org/domaframework/doma/intellij/document` +- **Provider**: Registers documentation display extension points in IntelliJ. + - **Class Naming Rules**: Use the `DocumentationProvider` suffix. +- **Generator**: Generates HTML for documentation display. + - **DocumentDaoParameterGenerator**: Generates documentation for bind variable elements starting from DAO parameters. + - **DocumentStaticFieldAccessGenerator**: Generates documentation for bind variable elements starting from static field access. + - **Class Naming Rules**: Use the `DocumentationGenerator` suffix. + +### Formatter +Functionality for formatting SQL. +- **Feature Package**: `src/main/kotlin/org/domaframework/doma/intellij/formatter` +- **Builder**: Entry point for formatting, implements the `FormattingModelBuilder` class. + - **SqlFormattingModelBuilder**: Provides formatting models for SQL. + - **SqlBlockRelationBuilder**: Sets parent-child relationships between blocks. + - **SqlBlockBuilder**: Manages the start and end blocks of conditional directives and group blocks. + - **SqlCustomSpacingBuilder**: Defines custom spacing settings for element types and blocks. + - **Class Naming Rules**: Use the `FormattingModelBuilder` suffix. +- **Block**: Classes representing the basic unit of formatting blocks. + - The abstract class `SqlBlock` is the base, and blocks are structured hierarchically according to the SQL structure. + - **SqlKeywordGroupBlock**: Represents keyword group blocks. + - **SqlSubGroupBlock**: Represents subgroups enclosed in `()`. + - **SqlElBlockCommentBlock**: Represents directive blocks such as `/*%if*/` and `/*%for*/`. + - Whether to preserve a newline before a block is determined by `isSaveSpace()`. + - The parent group block is held in `parentBlock`. + - The block's own indent is calculated by `createBlockIndentLen()`, and the indent base for child elements in its group is calculated by `createGroupIndentLen()`. + - **Class Naming Rules**: Use the `Block` suffix. +- **Util**: Utility classes related to formatting. + - Provides block object generation by branching and line break determination by keyword combinations. + - **Class Naming Rules**: Use the `Util` suffix. +- **Handler**: Provides custom spacing settings and block class determination according to query type. +- **Processor**: Classes that determine spacing between blocks. + - **InjectionSqlFormatter**: Provides common formatting for injected SQL. + - **SqlInjectionPostProcessor**: Applies formatting to injected SQL in DAOs. Independently invokes formatting and executes reformatting from the `SqlFormatPreProcessor` for SQL. + - **SqlFormatPreProcessor**: Inserts line breaks before the main SQL formatting process. Not automatically executed for injected SQL formatting. + - **SqlFormatPostProcessor**: Removes trailing spaces and adds a newline at the end of SQL after formatting. + - **Class Naming Rules**: Use the `Processor` suffix. +- **Visitor**: Visitor classes for collecting target elements to process within Processor. + - **Class Naming Rules**: Use the `Visitor` suffix