Skip to content

feat(mpp-idea): add NanoDSL language support with syntax highlighting#523

Closed
phodal wants to merge 1 commit intomasterfrom
feat/nanodsl-syntax-highlighting
Closed

feat(mpp-idea): add NanoDSL language support with syntax highlighting#523
phodal wants to merge 1 commit intomasterfrom
feat/nanodsl-syntax-highlighting

Conversation

@phodal
Copy link
Owner

@phodal phodal commented Dec 21, 2025

Summary

This PR adds NanoDSL language support for IntelliJ IDEA with syntax highlighting.

Changes

New Module: nanodsl-lang

Added a new language support module at mpp-idea/mpp-idea-exts/nanodsl-lang/ following the same architecture as devins-lang.

Features

  • Lexer (NanoDSLLexer.flex): Complete token definitions for NanoDSL syntax
  • Parser (NanoDSLParser.bnf): Grammar rules for NanoDSL language structure
  • Syntax Highlighting (NanoDSLSyntaxHighlighter.kt): Color scheme mappings
  • File Type (NanoDSLFileType.kt): .nanodsl file extension registration

Supported Syntax Elements

Category Elements
Keywords component, state, request, if, for, in, content
Layout Components VStack, HStack, Card, SplitView, GenCanvas, Form, Modal
Display Components Text, Image, Badge, Divider, Alert, Progress, Spinner, DataChart, DataTable
Input Components Button, Input, TextArea, Select, Checkbox, Radio, RadioGroup, Switch, NumberInput, SmartTextField, Slider, DatePicker, DateRangePicker
Operators << (bind read), := (bind write), +=, -=, *=, /=
Actions Navigate, Fetch, ShowToast, StateMutation
Event Handlers on_click, on_success, on_error, on_close, on_row_click
HTTP Methods GET, POST, PUT, PATCH, DELETE
Types int, float, string, bool

Color Scheme

  • Keywords → Bold keyword color
  • Components → Class name color
  • Actions → Static method color
  • Event Handlers → Instance method color
  • Operators → Operation sign color
  • Strings/Numbers → String/Number color
  • Comments → Line comment color (#)

Example

component CounterCard:
    state:
        count: int = 0

    Card:
        content:
            VStack:
                Text(content << f"Count: {state.count}")
                HStack:
                    Button("-"):
                        on_click: state.count -= 1
                    Button("+"):
                        on_click: state.count += 1

Build Verification

  • ✅ Lexer generation successful
  • ✅ Parser generation successful
  • ✅ Kotlin compilation successful
  • ✅ Module build successful

Pull Request opened by Augment Code with guidance from the PR author

Summary by CodeRabbit

  • New Features
    • Added full NanoDSL language support to the IDE with syntax highlighting, parser integration, and .nanodsl file recognition. Enables editing and parsing of NanoDSL code including UI components, state management, HTTP requests, and control structures.

✏️ Tip: You can customize this high-level summary in your review settings.

- Add nanodsl-lang module with complete lexer and parser definitions
- Implement syntax highlighting for NanoDSL keywords, components, operators
- Support for .nanodsl file extension
- Highlight keywords: component, state, request, if, for, in, content
- Highlight layout components: VStack, HStack, Card, SplitView, etc.
- Highlight display components: Text, Image, Badge, Alert, etc.
- Highlight input components: Button, Input, TextArea, Select, etc.
- Highlight operators: << (bind read), := (bind write), +=, -=, *=, /=
- Highlight actions: Navigate, Fetch, ShowToast, StateMutation
- Highlight event handlers: on_click, on_success, on_error, etc.
- Highlight HTTP methods: GET, POST, PUT, PATCH, DELETE
- Highlight types: int, float, string, bool
Copilot AI review requested due to automatic review settings December 21, 2025 12:42
@coderabbitai
Copy link

coderabbitai bot commented Dec 21, 2025

Walkthrough

This pull request introduces a new Gradle subproject :mpp-idea-exts:nanodsl-lang that adds full IntelliJ IDE language support for NanoDSL. It includes Grammarkit-based lexer and parser generation, PSI infrastructure, syntax highlighting, language registration, and build integration to embed the language plugin into the main plugin artifact.

Changes

Cohort / File(s) Change Summary
Build Configuration
mpp-idea/build.gradle.kts, mpp-idea/settings.gradle.kts
Registers new :mpp-idea-exts:nanodsl-lang subproject; configures Grammarkit plugin with lexer/parser generation tasks (generateLexer, generateParser); wires task dependencies to KotlinCompile; adds module as implementation dependency; aggregates resources into main plugin jar.
Grammar Definitions
mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLLexer.flex, src/grammar/NanoDSLParser.bnf
Defines NanoDSL token types (keywords, operators, literals, punctuation) and comprehensive grammar rules for component declarations, state/request blocks, conditional/loop constructs, expressions, and UI component composition.
Language Core
src/main/kotlin/.../language/NanoDSLLanguage.kt, NanoDSLFileType.kt
Establishes language identity and file type association; NanoDSLLanguage extends Language with display name; NanoDSLFileType registers .nanodsl extension and metadata.
Lexer & Token Types
src/main/kotlin/.../lexer/NanoDSLLexerAdapter.kt, NanoDSLTokenType.kt, .../psi/NanoDSLElementType.kt
Wraps generated lexer via FlexAdapter; defines token and element type classes for PSI infrastructure.
Syntax Highlighting
src/main/kotlin/.../highlight/NanoDSLSyntaxHighlighter.kt, NanoDSLSyntaxHighlighterFactory.kt
Implements token-to-visual-attribute mapping for keywords, operators, components, actions, HTTP methods, types, literals, and punctuation using IntelliJ DefaultLanguageHighlighterColors.
PSI & Parser Integration
src/main/kotlin/.../parser/NanoDSLParserDefinition.kt, .../psi/NanoDSLFile.kt
Wires lexer, parser, and file type; defines comment/string/whitespace token sets; provides PSI file representation and element creation from AST nodes.
Plugin Registration
src/main/resources/cc.unitmesh.nanodsl.language.xml
Registers FileType, ParserDefinition, and SyntaxHighlighterFactory extensions with the IntelliJ plugin platform.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Grammarkit configuration: Verify generateLexer/generateParser task setup, source/output paths, and Gradle task dependency ordering are correct
  • Grammar correctness: Review NanoDSLLexer.flex and NanoDSLParser.bnf for token/rule completeness, proper keyword/operator definitions, and grammar rule consistency (e.g., component composition, binding operators, property assignments)
  • Syntax highlighting mappings: Validate token-set groupings and TextAttributesKey assignments cover all relevant keywords and language constructs
  • PSI infrastructure: Confirm ParserDefinition and File implementations properly integrate with IntelliJ's file-handling system, and resource aggregation in root build config is correct
  • Build integration: Check that module is correctly included in subproject dependencies and resource copying

Possibly related PRs

Poem

🐰 A lexer hops, a parser bounds,
Grammar rules plant fertile grounds,
PSI elements grow so bright,
Syntax highlighting sets it right—
NanoDSL springs to life, what a sight! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding NanoDSL language support with syntax highlighting to the mpp-idea plugin.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/nanodsl-syntax-highlighting

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@augmentcode
Copy link

augmentcode bot commented Dec 21, 2025

🤖 Augment PR Summary

Summary: Adds first-class NanoDSL support to the AutoDev IntelliJ plugin so NanoDSL files can be recognized and highlighted.

Changes:

  • Introduced a new extension module mpp-idea-exts:nanodsl-lang with GrammarKit/JFlex integration.
  • Wired the module into the main mpp-idea build (resources packaging + dependency) and included it in settings.gradle.kts.
  • Added NanoDSL lexer (NanoDSLLexer.flex) and BNF grammar (NanoDSLParser.bnf) plus generated lexer/parser/PSI sources under src/gen.
  • Implemented IntelliJ language scaffolding: NanoDSLLanguage, NanoDSLFileType, PSI file, element/token types, lexer adapter, and parser definition.
  • Added NanoDSL syntax highlighting via NanoDSLSyntaxHighlighter and factory with token-to-color mappings.
  • Registered file type, parser definition, and syntax highlighter in cc.unitmesh.nanodsl.language.xml for .nanodsl files.

Technical Notes: Uses GrammarKit tasks (generateLexer/generateParser) during build; highlighting is primarily lexer-driven while PSI infrastructure is also registered for parsing support.

🤖 Was this summary useful? React with 👍 or 👎

Copy link

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

companion object {
val FILE = IFileElementType(cc.unitmesh.nanodsl.language.NanoDSLLanguage)
val COMMENTS = TokenSet.create(NanoDSLTypes.COMMENT)
val WHITESPACES = TokenSet.EMPTY
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getWhitespaceTokens() currently returns TokenSet.EMPTY, so TokenType.WHITE_SPACE may not be skipped during parsing and most real NanoDSL files (with spaces/indentation) can fail to parse. devins-lang includes TokenType.WHITE_SPACE via ShireTokenTypeSets.WHITESPACES.

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎


requestEntry ::= (URL | METHOD | BODY | HEADERS | ON_SUCCESS | ON_ERROR) COLON expr NEWLINE

propertyAssignment ::= IDENTIFIER COLON expr NEWLINE
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

propertyAssignment only allows IDENTIFIER as the key, but the lexer emits dedicated tokens for common keys like on_click/content/method/url, so the PR’s example (e.g., on_click: ..., Text(content << ...)) likely won’t parse and will show errors. This looks like a lexer/parser token-mismatch rather than an input issue.

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎


forBlock ::= FOR IDENTIFIER IN expr COLON NEWLINE componentInstances

expr ::= STRING | NUMBER | BOOLEAN | IDENTIFIER (DOT IDENTIFIER)* | actionCall | binaryExpr
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In expr, the IDENTIFIER (DOT IDENTIFIER)* alternative appears before binaryExpr, so input like state.count += 1 will likely be consumed as just state.count (leaving += 1), causing parse errors in places expecting a full expression. This makes assignment-style operators hard to parse reliably with the current rule ordering.

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (4)
mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLLexer.flex (1)

25-25: Remove unused pattern definitions.

The SPACE (line 25) and INDENT (line 33) patterns are defined but never referenced in the token matching rules section (lines 132-242). Since only WHITE_SPACE, NEWLINE, and COMMENT are used for whitespace handling, these unused patterns should be removed to improve code clarity.

🔎 Proposed fix
-SPACE                    = [ \t\n\x0B\f\r]+
 IDENTIFIER               = [a-zA-Z_][a-zA-Z0-9_]*
 NUMBER                   = [0-9]+(\.[0-9]+)?
 BOOLEAN                  = true|false
 STRING                   = \"([^\\\"\r\n]|\\[^\r\n])*\"
 COMMENT                  = #[^\r\n]*
 NEWLINE                  = \n | \r | \r\n
 WHITE_SPACE              = [ \t]+
-INDENT                   = [ ][ ][ ][ ]+

Also applies to: 33-33

mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/highlight/NanoDSLSyntaxHighlighterFactory.kt (1)

7-9: LGTM! Standard factory implementation.

The factory correctly instantiates and returns the syntax highlighter. The current approach of creating a new instance is standard practice in IntelliJ plugins and works well.

Optionally, since NanoDSLSyntaxHighlighter is stateless, you could optimize by using a singleton instance:

🔎 Optional singleton optimization
 class NanoDSLSyntaxHighlighterFactory : SyntaxHighlighterFactory() {
-    override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?) = NanoDSLSyntaxHighlighter()
+    override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?) = INSTANCE
+    
+    companion object {
+        private val INSTANCE = NanoDSLSyntaxHighlighter()
+    }
 }
mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/NanoDSLFileType.kt (1)

6-14: Consider adding a file type icon.

The implementation is correct, but returning null for getIcon() means .nanodsl files won't have a distinctive icon in the Project view. Consider adding a custom icon to improve discoverability.

This is optional and can be addressed in a follow-up.

mpp-idea/build.gradle.kts (1)

897-943: Remove unused kotlin.serialization plugin.

The org.jetbrains.kotlin.plugin.serialization plugin is applied but has no usage in the nanodsl-lang module—no @Serializable annotations or kotlinx.serialization imports exist. Consider removing it to reduce build complexity, following the pattern where only modules with actual serialization needs (like devins-lang) apply the plugin.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6273af0 and 0f07493.

⛔ Files ignored due to path filters (56)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/lexer/_NanoDSLLexer.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/parser/NanoDSLParser.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLActionCall.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLActionName.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLArg.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLArgList.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLBinaryExpr.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLComponentBody.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLComponentDecl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLComponentInstance.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLComponentInstances.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLComponentName.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLContentBlock.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLExpr.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLForBlock.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLIfBlock.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLParam.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLParamList.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLProp.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLPropList.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLPropertyAssignment.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLRequestBlock.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLRequestEntries.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLRequestEntry.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLStateBlock.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLStateEntries.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLStateEntry.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLTypeRef.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLTypes.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/NanoDSLVisitor.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLActionCallImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLActionNameImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLArgImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLArgListImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLBinaryExprImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLComponentBodyImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLComponentDeclImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLComponentInstanceImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLComponentInstancesImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLComponentNameImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLContentBlockImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLExprImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLForBlockImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLIfBlockImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLParamImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLParamListImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLPropImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLPropListImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLPropertyAssignmentImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLRequestBlockImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLRequestEntriesImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLRequestEntryImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLStateBlockImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLStateEntriesImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLStateEntryImpl.java is excluded by !**/gen/**
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/psi/impl/NanoDSLTypeRefImpl.java is excluded by !**/gen/**
📒 Files selected for processing (14)
  • mpp-idea/build.gradle.kts (3 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLLexer.flex (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/NanoDSLFileType.kt (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/NanoDSLLanguage.kt (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/highlight/NanoDSLSyntaxHighlighter.kt (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/highlight/NanoDSLSyntaxHighlighterFactory.kt (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/lexer/NanoDSLLexerAdapter.kt (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/lexer/NanoDSLTokenType.kt (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/parser/NanoDSLParserDefinition.kt (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/psi/NanoDSLElementType.kt (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/psi/NanoDSLFile.kt (1 hunks)
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/resources/cc.unitmesh.nanodsl.language.xml (1 hunks)
  • mpp-idea/settings.gradle.kts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.kt

📄 CodeRabbit inference engine (AGENTS.md)

**/*.kt: Use expect/actual pattern for platform-specific code (for example: Platform implementations)
Use concrete classes (not interfaces) and Promise (not Flow) for @JsExport annotations
Avoid emoji and UTF-8 characters in WASM code
When modifying CodingAgentRenderer, update ALL implementations: DefaultCodingAgentRenderer, ComposeRenderer, JewelRenderer, ServerSideRenderer, and JsRendererAdapter in Kotlin
When modifying CodingAgentRenderer, update JVM CLI implementations: CodingCliRenderer and ConsoleRenderer
Use AutoDevColors or MaterialTheme.colorScheme for Compose styling

Files:

  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/psi/NanoDSLElementType.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/lexer/NanoDSLTokenType.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/NanoDSLFileType.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/parser/NanoDSLParserDefinition.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/highlight/NanoDSLSyntaxHighlighter.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/lexer/NanoDSLLexerAdapter.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/NanoDSLLanguage.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/psi/NanoDSLFile.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/highlight/NanoDSLSyntaxHighlighterFactory.kt
**/*.{kt,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never use hardcoded colors - always use design tokens from the design system

Files:

  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/psi/NanoDSLElementType.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/lexer/NanoDSLTokenType.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/NanoDSLFileType.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/parser/NanoDSLParserDefinition.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/highlight/NanoDSLSyntaxHighlighter.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/lexer/NanoDSLLexerAdapter.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/NanoDSLLanguage.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/psi/NanoDSLFile.kt
  • mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/highlight/NanoDSLSyntaxHighlighterFactory.kt
🧠 Learnings (1)
📚 Learning: 2025-12-07T08:40:10.859Z
Learnt from: CR
Repo: phodal/auto-dev PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T08:40:10.859Z
Learning: Run `./gradlew :mpp-ui:generateI18n4kFiles` command when updating i18n resources

Applied to files:

  • mpp-idea/build.gradle.kts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: CodeQL analysis (java)
  • GitHub Check: Build
🔇 Additional comments (17)
mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/lexer/NanoDSLLexerAdapter.kt (1)

1-5: LGTM! Standard IntelliJ lexer adapter pattern.

The implementation correctly wraps the JFlex-generated _NanoDSLLexer using FlexAdapter, following IntelliJ Platform conventions for language plugin development. The adapter will properly integrate the lexer with the syntax highlighter and parser definition.

mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLLexer.flex (1)

238-239: Good practice: IDENTIFIER rule correctly positioned.

The IDENTIFIER rule is correctly placed as the last pattern match before the fallback rule. This ensures that all keywords and component names are matched first, preventing them from being incorrectly tokenized as identifiers.

mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/highlight/NanoDSLSyntaxHighlighter.kt (3)

12-17: LGTM! Standard IntelliJ syntax highlighter pattern.

The class correctly extends SyntaxHighlighterBase and implements the required methods following IntelliJ platform conventions.


23-128: Excellent token categorization!

The token sets are well-organized into semantic categories (keywords, event handlers, components, actions, etc.) and comprehensively cover the NanoDSL syntax elements described in the PR objectives.


130-156: Well-structured color mappings using design system tokens.

The attribute mappings appropriately use DefaultLanguageHighlighterColors design tokens throughout, following the coding guideline to avoid hardcoded colors. Semantic mappings are sensible: keywords as KEYWORD, components as CLASS_NAME, actions as STATIC_METHOD, etc.

Also applies to: 162-181

mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/resources/cc.unitmesh.nanodsl.language.xml (1)

1-26: LGTM! Properly configured plugin descriptor.

The plugin descriptor correctly registers all necessary extension points for NanoDSL language support:

  • File type association for .nanodsl extension
  • Parser definition for language parsing
  • Syntax highlighter factory for editor highlighting

The structure follows standard IntelliJ plugin conventions.

mpp-idea/settings.gradle.kts (1)

37-38: LGTM!

The new nanodsl-lang module is correctly added to the extension modules include block, following the established pattern.

mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/lexer/NanoDSLTokenType.kt (1)

1-9: LGTM!

Standard IntelliJ token type implementation. The toString() override provides helpful debugging context by prefixing with the class name.

mpp-idea/build.gradle.kts (1)

222-222: LGTM!

The resource inclusion and dependency wiring for nanodsl-lang follows the established pattern used by other extension modules.

Also applies to: 335-335

mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/psi/NanoDSLElementType.kt (1)

1-7: LGTM!

Standard IntelliJ PSI element type implementation correctly bound to NanoDSLLanguage.

mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/NanoDSLLanguage.kt (1)

1-8: LGTM!

Standard IntelliJ language singleton implementation. The getDisplayName() override is technically redundant since the Language base class uses the constructor parameter as the display name by default, but keeping it explicit is fine for clarity.

mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/psi/NanoDSLFile.kt (1)

1-14: LGTM!

Standard IntelliJ PSI file implementation correctly wiring NanoDSLLanguage and NanoDSLFileType.

mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/parser/NanoDSLParserDefinition.kt (1)

24-38: LGTM!

The parser definition methods are correctly implemented, properly wiring the lexer adapter, generated parser, and PSI factory.

mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf (4)

1-13: LGTM! Parser metadata is properly configured.

The Grammar-Kit configuration follows IntelliJ conventions with appropriate package structure and PSI generation settings.


110-138: LGTM! Basic grammar structure is well-defined.

The root rule and structural elements (components, state blocks, request blocks) are clearly defined with proper handling of significant whitespace.


17-17: The cross-platform newline handling is already correctly implemented in the actual JFlex lexer (NanoDSLLexer.flex), which defines NEWLINE = \n | \r | \r\n. The BNF pattern is only for IDE preview purposes and does not affect the production lexer's behavior. No changes needed.

Likely an incorrect or invalid review comment.


164-164: The expr rule grammar is unambiguous and correctly handles its intended design.

The expr rule's alternatives (STRING, NUMBER, BOOLEAN, IDENTIFIER with optional DOT chains, actionCall, binaryExpr) are sufficiently distinguishable without requiring additional precedence levels. The binaryExpr rule supports only compound assignment operators (+=, -=, *=, /=), which are explicit and non-overlapping. PEG's ordered choice correctly resolves the alternatives without ambiguity.

The suggested test case (count += state.value + 1) cannot parse because the DSL does not define the + operator—only compound assignments (+=, -=, *=, /=) are supported. Separating expression levels is unnecessary for the current design.

Likely an incorrect or invalid review comment.

Comment on lines +16 to +17
%class NanoDSLLexer
%class _NanoDSLLexer
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Remove duplicate %class directive - JFlex syntax error.

JFlex only allows one %class directive per lexer specification. Having both %class NanoDSLLexer and %class _NanoDSLLexer is invalid syntax.

Based on standard IntelliJ plugin patterns, you should keep only %class _NanoDSLLexer (the generated class with underscore prefix), and create a separate Kotlin/Java wrapper class named NanoDSLLexer that adapts the generated lexer.

🔎 Proposed fix
-%class NanoDSLLexer
 %class _NanoDSLLexer
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
%class NanoDSLLexer
%class _NanoDSLLexer
%class _NanoDSLLexer
🤖 Prompt for AI Agents
In mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLLexer.flex around
lines 16-17, remove the duplicate %class directive so only %class _NanoDSLLexer
remains (JFlex permits a single %class). Then create or keep a separate
Kotlin/Java wrapper class named NanoDSLLexer that instantiates and delegates to
the generated _NanoDSLLexer (adapting constructors/method signatures as needed)
so external code uses NanoDSLLexer while the generated lexer class keeps the
underscore name.

Comment on lines +140 to +142
componentInstance ::= componentName propList? COLON NEWLINE componentBody
| componentName LPAREN argList? RPAREN COLON? NEWLINE? componentBody?
| componentName LPAREN argList? RPAREN NEWLINE?
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -name "NanoDSLParser.bnf" -type f

Repository: phodal/auto-dev

Length of output: 126


🏁 Script executed:

fd "NanoDSLParser" --type f

Repository: phodal/auto-dev

Length of output: 493


🏁 Script executed:

find . -path "*nanodsl*" -o -path "*nano-dsl*" | grep -E "\.(bnf|test|sample)" | head -20

Repository: phodal/auto-dev

Length of output: 126


🏁 Script executed:

cat -n ./mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf | sed -n '130,155p'

Repository: phodal/auto-dev

Length of output: 1344


🏁 Script executed:

wc -l ./mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf

Repository: phodal/auto-dev

Length of output: 130


🏁 Script executed:

cat ./mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf | head -150 | tail -30

Repository: phodal/auto-dev

Length of output: 1289


🏁 Script executed:

cat ./xiuper-ui/src/jvmTest/kotlin/cc/unitmesh/xuiper/dsl/NanoDSLParserTest.kt | grep -A 10 -B 2 "Button\|componentInstance\|LPAREN"

Repository: phodal/auto-dev

Length of output: 5842


🏁 Script executed:

cat ./xiuper-ui/src/commonTest/kotlin/cc/unitmesh/xuiper/dsl/NanoDSLParserCommonTest.kt | head -100

Repository: phodal/auto-dev

Length of output: 2579


🏁 Script executed:

grep -A 5 -B 5 "componentInstance" ./mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf

Repository: phodal/auto-dev

Length of output: 1412


Line 142 is redundant and unreachable due to rule ordering.

The second alternative at line 141 (componentName LPAREN argList? RPAREN COLON? NEWLINE? componentBody?) will always match inputs that line 142 attempts to match, because all its elements are optional. Since PEG uses ordered choice with first-match semantics, where the first alternative that succeeds is used and subsequent alternatives are ignored, line 142 will never be reached. Remove the redundant third alternative.

🤖 Prompt for AI Agents
In mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf around
lines 140 to 142, the third alternative (line 142) is redundant and unreachable
because the preceding alternative (line 141) has optional COLON, NEWLINE and
componentBody, which will always match the same inputs first under PEG ordered
choice; remove the third alternative so the rule reads only the first two
alternatives (componentName propList? COLON NEWLINE componentBody and
componentName LPAREN argList? RPAREN COLON? NEWLINE? componentBody?) to
eliminate dead/unreachable grammar.


actionName ::= NAVIGATE | FETCH | SHOWTOAST | STATEMUTATION

binaryExpr ::= expr (PLUS_EQUALS | MINUS_EQUALS | TIMES_EQUALS | DIV_EQUALS) expr
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd mpp-idea/mpp-idea-exts/nanodsl-lang && find . -name "*.bnf" -o -name "*.flex" | head -20

Repository: phodal/auto-dev

Length of output: 122


🏁 Script executed:

cat -n mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf | sed -n '150,180p'

Repository: phodal/auto-dev

Length of output: 825


🏁 Script executed:

grep -n "PLUS\|MINUS\|TIMES\|DIV\|expr" mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf

Repository: phodal/auto-dev

Length of output: 1015


🏁 Script executed:

cat -n mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf | head -80

Repository: phodal/auto-dev

Length of output: 3376


🏁 Script executed:

grep -E "PLUS[^_]|MINUS[^_]|TIMES[^_]|DIV[^_]|\s\+\s|\s-\s|\s\*\s|\s/\s" mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf

Repository: phodal/auto-dev

Length of output: 197


🏁 Script executed:

cat -n mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf | tail -20

Repository: phodal/auto-dev

Length of output: 764


🏁 Script executed:

cat -n mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLLexer.flex

Repository: phodal/auto-dev

Length of output: 9693


Clarify design intent: binaryExpr currently lacks arithmetic operators.

The binaryExpr rule at line 170 contains only compound assignment operators (+=, -=, *=, /=). Simple arithmetic operators (+, -, *, /) are not defined in the grammar at all. This means NanoDSL cannot perform basic arithmetic operations like a + b—only compound assignments like a += b.

Issues:

  • The rule name binaryExpr is misleading; it should reflect that it handles only compound assignment
  • If arithmetic operations are required, define and add arithmetic operator tokens (PLUS, MINUS, TIMES, DIV) and extend the rule accordingly
  • If arithmetic is intentionally excluded, clarify this design decision and rename the rule to avoid confusion
🤖 Prompt for AI Agents
In mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLParser.bnf around line
170, the binaryExpr rule only includes compound-assignment operators
(PLUS_EQUALS, MINUS_EQUALS, TIMES_EQUALS, DIV_EQUALS) which prevents simple
arithmetic expressions and makes the rule name misleading; either rename the
rule to indicate it handles only compound assignments (e.g., compoundAssignExpr)
or extend it to include simple arithmetic by adding tokens for PLUS, MINUS,
TIMES, DIV and allowing expr (
(PLUS|MINUS|TIMES|DIV|PLUS_EQUALS|MINUS_EQUALS|TIMES_EQUALS|DIV_EQUALS) expr )
so both binary arithmetic and compound assignment are supported—choose and apply
one of these two fixes and update any references/docs accordingly.

Comment on lines +157 to +160
// Literals
ATTRIBUTES[NanoDSLTypes.STRING] = DefaultLanguageHighlighterColors.STRING
ATTRIBUTES[NanoDSLTypes.NUMBER] = DefaultLanguageHighlighterColors.NUMBER
ATTRIBUTES[NanoDSLTypes.BOOLEAN] = DefaultLanguageHighlighterColors.KEYWORD
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider using a more appropriate color for boolean literals.

Boolean literals (true/false) are typically styled as literals rather than keywords. While the current mapping works, consider using DefaultLanguageHighlighterColors.NUMBER or keeping the default literal styling for semantic consistency.

🔎 Suggested alternative
 // Literals
 ATTRIBUTES[NanoDSLTypes.STRING] = DefaultLanguageHighlighterColors.STRING
 ATTRIBUTES[NanoDSLTypes.NUMBER] = DefaultLanguageHighlighterColors.NUMBER
-ATTRIBUTES[NanoDSLTypes.BOOLEAN] = DefaultLanguageHighlighterColors.KEYWORD
+ATTRIBUTES[NanoDSLTypes.BOOLEAN] = DefaultLanguageHighlighterColors.NUMBER
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Literals
ATTRIBUTES[NanoDSLTypes.STRING] = DefaultLanguageHighlighterColors.STRING
ATTRIBUTES[NanoDSLTypes.NUMBER] = DefaultLanguageHighlighterColors.NUMBER
ATTRIBUTES[NanoDSLTypes.BOOLEAN] = DefaultLanguageHighlighterColors.KEYWORD
// Literals
ATTRIBUTES[NanoDSLTypes.STRING] = DefaultLanguageHighlighterColors.STRING
ATTRIBUTES[NanoDSLTypes.NUMBER] = DefaultLanguageHighlighterColors.NUMBER
ATTRIBUTES[NanoDSLTypes.BOOLEAN] = DefaultLanguageHighlighterColors.NUMBER
🤖 Prompt for AI Agents
In
mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/highlight/NanoDSLSyntaxHighlighter.kt
around lines 157-160, the BOOLEAN token is mapped to
DefaultLanguageHighlighterColors.KEYWORD; change this mapping to a literal-style
color (for example DefaultLanguageHighlighterColors.NUMBER or
DefaultLanguageHighlighterColors.STRING) so boolean literals are highlighted as
literals rather than keywords, update the ATTRIBUTES[NanoDSLTypes.BOOLEAN]
assignment accordingly and ensure imports remain valid.

Comment on lines +17 to +22
class NanoDSLParserDefinition : ParserDefinition {
companion object {
val FILE = IFileElementType(cc.unitmesh.nanodsl.language.NanoDSLLanguage)
val COMMENTS = TokenSet.create(NanoDSLTypes.COMMENT)
val WHITESPACES = TokenSet.EMPTY
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the NanoDSL lexer definition
echo "=== Checking for NanoDSL lexer files ==="
find mpp-idea/mpp-idea-exts/nanodsl-lang -type f -name "*Lexer*" | head -10

echo ""
echo "=== Checking for grammar files ==="
find mpp-idea/mpp-idea-exts/nanodsl-lang -type f -name "*.flex" -o -name "*.bnf" | head -10

echo ""
echo "=== Looking at NanoDSLParserDefinition.kt ==="
cat mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/parser/NanoDSLParserDefinition.kt

Repository: phodal/auto-dev

Length of output: 2083


🏁 Script executed:

#!/bin/bash
# Check devins-lang ParserDefinition for whitespace handling
echo "=== Checking devins-lang ParserDefinition ==="
find mpp-idea/mpp-idea-exts/devins-lang -type f -name "*ParserDefinition*" -o -name "*Parser.kt" | head -5

echo ""
echo "=== Looking at devins-lang implementations ==="
rg "WHITESPACE|TokenSet.EMPTY" mpp-idea/mpp-idea-exts/devins-lang/src/main/kotlin/ --type kt -B2 -A2 2>/dev/null | head -50

Repository: phodal/auto-dev

Length of output: 479


🏁 Script executed:

#!/bin/bash
# Check the NanoDSL lexer definition
echo "=== Checking NanoDSLLexer.flex ==="
cat mpp-idea/mpp-idea-exts/nanodsl-lang/src/grammar/NanoDSLLexer.flex

echo ""
echo "=== Checking for whitespace handling in generated lexer ==="
head -150 mpp-idea/mpp-idea-exts/nanodsl-lang/src/gen/cc/unitmesh/nanodsl/language/lexer/_NanoDSLLexer.java | grep -A5 -B5 "WHITE_SPACE"

Repository: phodal/auto-dev

Length of output: 8088


🏁 Script executed:

#!/bin/bash
# Check DevInParserDefinition for comparison
echo "=== Checking DevInParserDefinition.kt ==="
cat mpp-idea/mpp-idea-exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/parser/DevInParserDefinition.kt

echo ""
echo "=== Check DevinsLexer.flex ==="
find mpp-idea/mpp-idea-exts/devins-lang -name "*Lexer.flex" -exec cat {} \;

Repository: phodal/auto-dev

Length of output: 21745


Declare whitespace tokens in getWhitespaceTokens() to match lexer output.

The NanoDSLLexer returns TokenType.WHITE_SPACE for whitespace, but the ParserDefinition declares WHITESPACES = TokenSet.EMPTY. Token types treated as whitespace by the PSI builder are automatically skipped by PsiBuilder. Change to TokenSet.create(TokenType.WHITE_SPACE) to properly handle whitespace tokens.

🤖 Prompt for AI Agents
In
mpp-idea/mpp-idea-exts/nanodsl-lang/src/main/kotlin/cc/unitmesh/nanodsl/language/parser/NanoDSLParserDefinition.kt
around lines 17 to 22, the parser currently declares WHITESPACES =
TokenSet.EMPTY but the lexer emits TokenType.WHITE_SPACE; update WHITESPACES to
include TokenType.WHITE_SPACE (e.g., TokenSet.create(TokenType.WHITE_SPACE)) so
the PSI builder treats lexer whitespace as skipped tokens, and ensure any
necessary import for TokenType is present.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive NanoDSL language support to the IntelliJ IDEA plugin, following the same architecture pattern as the existing devins-lang module. The implementation includes a complete language infrastructure with lexer, parser, PSI elements, syntax highlighting, and file type registration for .nanodsl files.

Key Changes:

  • New Language Module: Adds nanodsl-lang module with full language support infrastructure
  • Grammar Definitions: Implements lexer and parser grammar files for NanoDSL syntax
  • Syntax Highlighting: Provides color scheme mappings for keywords, components, actions, and other language elements

Reviewed changes

Copilot reviewed 70 out of 70 changed files in this pull request and generated 36 comments.

Show a summary per file
File Description
settings.gradle.kts Adds nanodsl-lang module to the build
build.gradle.kts Configures nanodsl-lang module with grammar-kit tasks and dependencies
cc.unitmesh.nanodsl.language.xml Registers language extensions for file type, parser, and syntax highlighter
NanoDSLLanguage.kt Defines the NanoDSL language object
NanoDSLFileType.kt Registers .nanodsl file extension
NanoDSLFile.kt Implements PSI file for NanoDSL
NanoDSLTokenType.kt Defines token type for lexer
NanoDSLElementType.kt Defines element type for parser
NanoDSLLexerAdapter.kt Adapts generated JFlex lexer
NanoDSLParserDefinition.kt Configures parser with token sets
NanoDSLSyntaxHighlighter.kt Maps tokens to IDE color schemes
NanoDSLSyntaxHighlighterFactory.kt Factory for syntax highlighter instances
NanoDSLLexer.flex JFlex grammar defining all tokens and keywords
NanoDSLParser.bnf BNF grammar defining language structure
Generated PSI files Auto-generated interfaces and implementations from parser grammar
Generated lexer/parser Auto-generated Java code from grammar files

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +16 to +17
%class NanoDSLLexer
%class _NanoDSLLexer
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lexer class is defined twice with both %class NanoDSLLexer and %class _NanoDSLLexer directives. This will cause the second directive to override the first, resulting in only the _NanoDSLLexer class being generated. Remove the duplicate %class directive on line 16.

Copilot uses AI. Check for mistakes.
import com.intellij.psi.TokenType;


class _NanoDSLLexer implements FlexLexer {
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused class: _NanoDSLLexer is not referenced within this codebase. If not used as an external API it should be removed.

Copilot uses AI. Check for mistakes.
super(node);
}

public void accept(@NotNull NanoDSLVisitor visitor) {
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method NanoDSLActionNameImpl.accept(..) could be confused with overloaded method accept, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.
super(node);
}

public void accept(@NotNull NanoDSLVisitor visitor) {
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method NanoDSLActionCallImpl.accept(..) could be confused with overloaded method accept, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.
super(node);
}

public void accept(@NotNull NanoDSLVisitor visitor) {
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method NanoDSLArgImpl.accept(..) could be confused with overloaded method accept, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.
public final int getTokenEnd() {
return getTokenStart() + yylength();
}

Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method overrides FlexLexer.reset; it is advisable to add an Override annotation.

Suggested change
@Override

Copilot uses AI. Check for mistakes.
public final int getTokenStart() {
return zzStartRead;
}

Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method overrides FlexLexer.getTokenEnd; it is advisable to add an Override annotation.

Suggested change
@Override

Copilot uses AI. Check for mistakes.
int offset = input & 255;
return offset == input ? ZZ_CMAP_BLOCKS[offset] : ZZ_CMAP_BLOCKS[ZZ_CMAP_TOP[input >> 8] | offset];
}

Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method overrides FlexLexer.getTokenStart; it is advisable to add an Override annotation.

Suggested change
@Override

Copilot uses AI. Check for mistakes.
parseLight(root_, builder_);
return builder_.getTreeBuilt();
}

Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method overrides LightPsiParser.parseLight; it is advisable to add an Override annotation.

Suggested change
@Override

Copilot uses AI. Check for mistakes.

@SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"})
public class NanoDSLParser implements PsiParser, LightPsiParser {

Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method overrides PsiParser.parse; it is advisable to add an Override annotation.

Suggested change
@Override

Copilot uses AI. Check for mistakes.
phodal added a commit that referenced this pull request Jan 10, 2026
- Add PDF skill for document analysis
- Add code review skill with structured criteria
- Add test generation skill for unit tests
- Add documentation generation skill
- Add refactoring skill for code quality improvements
- Include comprehensive README with usage instructions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments