Skip to content

Changelog update - v0.3.0-beta.5 - #214

Open
github-actions[bot] wants to merge 19 commits into
mainfrom
changelog-update-v0.3.0-beta.5
Open

Changelog update - v0.3.0-beta.5#214
github-actions[bot] wants to merge 19 commits into
mainfrom
changelog-update-v0.3.0-beta.5

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Current pull request contains patched CHANGELOG.md file for the v0.3.0-beta.5 version.

johmara and others added 19 commits May 26, 2026 14:34
…ity (Issue #42)

Grammar (FeatureModel.bnf):
- Add COMPONENT, LOGIC, OR_BLOCK, XOR_BLOCK, SUB_LOGIC grammar rules
- feature children are now COMPONENT* (feature | LOGIC) enabling proper group scoping
- Add QUESTIONMARK for optional feature syntax (?)
- Restore getFullLPQText() in methods[] (required by FeatureModelUtil)

Lexer (FeatureModel.flex):
- Add OR/XOR/QUESTIONMARK token support via character-by-character state machine
- Fix token definitions: OR="or", XOR="xor", QUESTIONMARK="?"
- New lexer states: or1/or2, xor1/xor2/xor3, returnOr/returnXor etc.

Generated PSI (src/main/gen):
- New types: FeatureModelComponent, FeatureModelLogic, FeatureModelOrBlock,
  FeatureModelXorBlock, FeatureModelSubLogic (+ Impl classes)
- Updated FeatureModelTypes: adds OR, XOR, QUESTIONMARK tokens + new element types
- Updated FeatureModelFeature: replaces getFeatureList() with getComponentList(),
  restores getFullLPQText()

Syntax highlighting:
- FeatureModelHighlightingLexer.flex: adds OR/XOR/QUESTIONMARK token rules
- FeatureModelSyntaxHighlighter: adds OR/XOR/QUESTIONMARK attribute keys (keyword style)
- FeatureModelAnnotator: removes forced feature coloring so keywords get own color
- HAnSDarcula.xml + HAnSDefault.xml: adds color entries for XOR_TOKEN/OR_TOKEN/OPTIONAL

Existing functionality preserved:
- PsiTreeUtil.collectElementsOfType still finds all FeatureModelFeature nodes
- getFullLPQText(), getLPQText(), all metrics/referencing APIs unchanged
- Plain feature hierarchy behavior unchanged

Note: LPQ resolution for features inside OR/XOR groups is limited (parent-chain
traversal in FeatureModelUtil only sees FeatureModelComponent, not FeatureModelFeature);
follow-up work needed for full LPQ support in grouped features.

Co-authored-by: Simon Osterheider <156541812+SimonOsterheider@users.noreply.github.com>
Co-authored-by: Cindy Liang <lmxcin@protonmail.com>
Co-authored-by: JoudiAlakkad <joudi.alakkad@outlook.com>
Co-authored-by: DSaatz <126864831+DSaatz@users.noreply.github.com>
Co-authored-by: ManhalJasem <96029523+ManhalJasem@users.noreply.github.com>
…ammar

The new XOR/OR grammar wraps every child feature in a COMPONENT node:
  Old: childFeature.getParent() == parentFeature
  New: childFeature.getParent() == FeatureModelComponent
       childFeature.getParent().getParent() == parentFeature

This broke LPQ resolution, full LPQ lookup, rename, and add-feature
for ALL nested features (not just XOR/OR groups).

Fixes:
- FeatureModelPsiImplUtil.getParentFeature(): new helper that traverses
  past COMPONENT/LOGIC/OR_BLOCK/XOR_BLOCK/SUB_LOGIC wrappers to find
  the nearest FeatureModelFeature ancestor (null = file root)

- getFullLPQStack(): skip non-FeatureModelFeature nodes in parent walk
  so COMPONENT wrapper nodes do not pollute the LPQ name stack

- findLPQRecursively(): replace feature.peek().getParent().getParent()
  with getParentFeature() so disambiguation works for any nesting depth
  regardless of intermediate wrapper nodes

- addFeatureToFeatureModel(): replace sibling-based indentation hack
  (which NPE'd because feature.getPrevSibling() is null inside COMPONENT)
  with column-based computation: feature column + 4, grammar-agnostic

- FeatureModelUtil.processSelectedFeatures(): replace
  feature.getParent() instanceof FeatureModelFeature
  with FeatureModelPsiImplUtil.getParentFeature(feature)
- Named groups (xor channel / or gateway): lexer already tokenizes these
  correctly; grammar XOR_BLOCK ::= XOR (SUB_LOGIC) handles inline name as
  first COMPONENT. No grammar change needed.

- GrammarKit Gradle plugin (org.jetbrains.grammarkit 2023.3.2.2) added to
  build.gradle.kts and libs.versions.toml with generateParser/generateLexer
  tasks for all four grammars (FeatureModel, CodeAnnotation, FileAnnotation,
  FolderAnnotation) plus FeatureModelHighlightingLexer. compileJava depends
  on all generation tasks.

- Parser/lexer tests: delete stale ParsingTestData.txt (COMPONENT wrappers
  now differ); add six new fixture files (PlainHierarchy, OrGroup, XorGroup,
  OptionalFeature, NamedXorGroup, KeywordPrefixedFeatures). On first run the
  framework auto-generates the .txt PSI dumps; second run is a passing check.

- Highlighting tests: new cases for or/xor keyword coloring, '?' operation
  sign, keyword-prefix false positives (orange/xorfoo), and named-group
  shorthand (xor channel).

- Qodana fixes (6 warnings):
  1. Remove unused PsiTreeUtil import
  2. Fix constant-value: prevSibling instanceof PsiFile -> getParent() instanceof PsiFile
  3+4. Add instanceof guards before FeatureModelFeature casts in findLPQRecursively
  5. Use explicit scope in ReferencesSearch.search()
  6. ReferencesSearch with GlobalSearchScope.projectScope instead of implicit scope
- Add org.jetbrains.grammarkit 2023.3.0.3 to libs.versions.toml
- Configure GenerateParserTask/GenerateLexerTask for all 4 grammars
  using new API: sourceFile, targetRootOutputDir, targetOutputDir
- Update idea-flex.skeleton: remove zzAtBOL/zzEOFDone declarations
  (JFlex 1.9.2 generates them internally; duplicate fields caused
  'variable already defined' compile errors when skeleton was applied)
- Add import com.intellij.lexer.FlexLexer to FeatureModel.flex and
  FeatureModelHighlightingLexer.flex (IDE GrammarKit added this
  automatically; CLI task does not)
- Declare metric methods in FeatureAnnotationNamedElement interface
  (getTanglingDegree, setScatteringDegree, etc.) so they are part of
  the interface contract rather than methods= in BNF
- Remove metric methods from BNF methods= (they lack static delegates
  in FeatureModelPsiImplUtil; GrammarKit 2023.3.0.3 is strict about this)
- Fix PsiElement→FeatureModelFeature parameter types in
  FeatureModelPsiImplUtil for getFullLPQText, getLPQText, getLPQStack,
  deleteFromFeatureModel, deleteFeature, deleteFeatureWithAnnotations,
  deleteFeatureWithCode (GrammarKit 2023.3.0.3 requires exact type match)
- Generation tasks are NOT wired to compileJava/compileKotlin; run
  them explicitly when .bnf/.flex files change
  (CLI parser generator omits method stubs it can't resolve; PSI
  interface files in src/main/gen/ are authoritative/committed)
…fixtures

- Update FeatureModel.bnf: OR_BLOCK/XOR_BLOCK now accept CRLF* between
  the keyword and SUB_LOGIC, so 'or' and 'xor' on their own line parse
  correctly (previously the newline caused PsiErrorElement)
- Regenerate FeatureModelParser.java: OR_BLOCK_1/XOR_BLOCK_1 helpers
  consume zero or more CRLF tokens before SUB_LOGIC
- Add PSI dump fixtures for all 7 parsing tests:
  PlainHierarchy, OrGroup, XorGroup, OptionalFeature,
  NamedXorGroup, KeywordPrefixedFeatures, ParsingTestData
  (generated by ParsingTestCase on first run; verified correct on second run)
- Add .gradle-isolated/ to .gitignore (local workaround for JetBrains
  Toolbox corrupting Gradle transform cache during builds)
- Add goIntoFeaturenameN(n) helper to FeatureModel.flex — same as
  goIntoFeaturename() but pushes back n characters instead of 1;
  needed when the full token text spans multiple chars consumed
  by intermediate state transitions
- Add rules in <indent> state for 'or{FEATURENAME}+' and
  'xor{FEATURENAME}+': JFlex longest-match picks these over the
  single-char 'o'/'x' rules, so 'orange' emits FEATURENAME('orange')
  rather than the incorrect OR + FEATURENAME('ange')
- Regenerate FeatureModelLexer.java (DFA grows from 62→67→41 states)
- Update KeywordPrefixedFeatures.txt fixture to reflect correct behavior
  (orange/xorfoo/ordinal are now full FEATURENAME tokens)
- Restore plugin.xml to main baseline: the original PR commit contained
  incorrect implementationClass paths (missing featureAnnotation/
  syntaxHighlighting sub-packages) that caused ClassNotFoundException
  in the full test suite
PR #201 grammar change wraps feature children in
COMPONENT/LOGIC/OR_BLOCK/XOR_BLOCK/SUB_LOGIC nodes. Several callers still
assumed direct PSI parent/child relationships, causing:

- Feature Model view collapsed to root (shallow getChildrenOfTypeAsList)
- Metrics view empty (ClassCastException in getChildFeatures/getParentFeature)
- IDE background-task pileup at startup (HansTrafficLightAction queued a
  GetFeatureFileMappings task on every update; broken casts blocked the
  cache from initializing, so each task redid the full scan)

Add wrapper-safe FeatureModelPsiImplUtil.getChildFeatures(PsiElement) and
route FeatureViewElement, ProjectMetricsService, FeatureReferenceUtil, and
FeatureModelPsiImplUtil (addFeature, moveFeatureWithChildren) through it
or through the existing getParentFeature helper. Add AtomicBoolean dedupe
to HansTrafficLightAction so concurrent update() calls don't pile up.

Also rewrite ProjectMetricsService.getRootFeatures using findFeatures +
isRootFeature filter, removing a latent infinite-loop bug in the prior
sibling-walk implementation.

Bumps version to 0.3.0-beta.2.
GetFeatureFileMappings (traffic-light) and GetProjectMetrics
(metrics tool window) both call FeatureLocationManager.getAllFeatureFileMappings
on startup. The double-checked isFullyInitialized guard alone was not
enough: both threads entered the guarded branch and ran
calculateAllFeatureFileMappings in parallel, each spending minutes inside
ReferencesSearch.search under tryRunReadActionInSmartMode. The resulting
read-lock pressure starved the EDT write-intent permit and triggered the
IDE freeze popup.

Add a per-project Object lock and wrap the calculation in
synchronized + double-checked isFullyInitialized. First caller computes,
subsequent callers block briefly, then see the populated cache and return
immediately.

Bumps version to 0.3.0-beta.3.
FeatureModelUtil.getFeatureModelFiles used GlobalSearchScope.allScope,
which also indexes feature-model fixtures under src/test/resources. When
the plugin was loaded into the HAnS project itself the Metrics view and
Feature Model view listed features from the parser-test fixtures.

Switch to GlobalSearchScopesCore.projectProductionScope so only files
under production source roots are picked up. Existing plugin tests use
light test fixtures whose copied files land in the production source
root of the synthetic test project, so they still find their fixtures.

Bumps version to 0.3.0-beta.4.
beta.4 used GlobalSearchScopesCore.projectProductionScope, which only
includes production source roots. A .feature-model file at the project
root (the most common placement) falls outside any source root and was
therefore dropped from the scan — Metrics view, Feature Model view, and
reference resolution all came up empty even on a minimal project.

Replace the scope with FeatureAnnotationSearchScope and extend its
contains() to also exclude test source content. The scope still covers
project content roots, so root-level feature models are picked up, while
test fixtures under src/test/resources/ stay out.

Bumps version to 0.3.0-beta.5.
@github-actions github-actions Bot added the release changelog Pull requests with release changelog update label May 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release changelog Pull requests with release changelog update

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants