Skip to content

Commit e2e30a0

Browse files
authored
Merge pull request #1349 from oraios/fix-duplicated-yaml-comments
Fix duplicated YAML comments
2 parents a098401 + 5e82077 commit e2e30a0

3 files changed

Lines changed: 25 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Status of the `main` branch. Changes prior to the next official version change w
55
* General:
66
- Support `serena --version` CLI command for displaying the current version #1347
77
- Fix: Check for ignored path ignored `.git` folder only at the top level, not in every subdirectory (`Project._is_ignored_relative_path`) #1350
8+
- Fix: Duplicate comments in re-saved YAML configuration files #1285
89

910
# v1.1.2 (2026-04-14)
1011

src/serena/config/serena_config.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
SERENA_MANAGED_DIR_NAME,
3232
)
3333
from serena.util.inspection import determine_programming_language_composition
34-
from serena.util.yaml import YamlCommentNormalisation, load_yaml, normalise_yaml_comments, save_yaml, transfer_missing_yaml_comments
34+
from serena.util.yaml import YamlCommentNormalisation, load_yaml, normalise_yaml_comments, save_yaml, transfer_yaml_comments
3535
from solidlsp.ls_config import Language
3636

3737
from ..analytics import RegisteredTokenCountEstimator
@@ -581,7 +581,7 @@ def save(self, project_yml_path: str, save_project_local_yml: bool = True) -> No
581581

582582
# transfer missing comments from the template file
583583
template_config, _ = self._load_yaml_dict(PROJECT_TEMPLATE_FILE, self.YAML_COMMENT_NORMALISATION)
584-
transfer_missing_yaml_comments(template_config, config_with_comments, self.YAML_COMMENT_NORMALISATION, force_update_all=True)
584+
transfer_yaml_comments(template_config, config_with_comments, self.YAML_COMMENT_NORMALISATION, force_update_all=True)
585585

586586
# save project.yml
587587
save_yaml(config_path, config_with_comments)
@@ -1063,7 +1063,7 @@ def save(self) -> None:
10631063
# For some keys, we force updates, because old comments are problematic/misleading.
10641064
normalise_yaml_comments(commented_yaml, YamlCommentNormalisation.LEADING_WITH_CONVERSION_FROM_TRAILING)
10651065
template_yaml = load_yaml(SERENA_CONFIG_TEMPLATE_FILE, comment_normalisation=YamlCommentNormalisation.LEADING)
1066-
transfer_missing_yaml_comments(template_yaml, commented_yaml, YamlCommentNormalisation.LEADING, force_update_all=True)
1066+
transfer_yaml_comments(template_yaml, commented_yaml, YamlCommentNormalisation.LEADING, force_update_all=True)
10671067

10681068
save_yaml(self.config_file_path, commented_yaml)
10691069

src/serena/util/yaml.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from enum import Enum
55
from typing import Any
66

7-
from ruamel.yaml import YAML, CommentToken, StreamMark
7+
from ruamel.yaml import YAML, CommentedSeq, CommentToken, StreamMark
88
from ruamel.yaml.comments import CommentedMap
99

1010
from serena.constants import SERENA_FILE_ENCODING
@@ -122,6 +122,20 @@ def trailing_to_leading(comment_entry: Any) -> Any:
122122
first_token.value = first_token.value[1:]
123123
return token_list
124124

125+
def remove_nested_comments() -> None:
126+
"""
127+
Removes nested comments, particularly of sequences, which incorrectly capture comments
128+
that are actually intended for top-level keys.
129+
"""
130+
for key in commented_map.keys():
131+
entry = commented_map[key]
132+
if isinstance(entry, CommentedSeq):
133+
items = entry.ca.items
134+
if isinstance(items, dict):
135+
items_keys = list(items.keys())
136+
for i in items_keys:
137+
items[i] = [None] * 4
138+
125139
match comment_normalisation:
126140
case YamlCommentNormalisation.NONE:
127141
pass
@@ -176,6 +190,9 @@ def trailing_to_leading(comment_entry: Any) -> Any:
176190
preceding_comment[ITEM_COMMENT_INDEX_BEFORE] = token_list
177191
current_comment[ITEM_COMMENT_INDEX_BEFORE] = None
178192
preceding_comment = current_comment
193+
194+
# remove nested comments, as we assume that only top-level keys are supposed to be commented
195+
remove_nested_comments()
179196
case _:
180197
raise ValueError(f"Unhandled comment normalisation: {comment_normalisation}")
181198

@@ -204,7 +221,7 @@ def yaml_comment_entry_is_empty(comment_entry: Any) -> bool:
204221
return False
205222

206223

207-
def transfer_missing_yaml_comments_by_index(
224+
def transfer_yaml_comments_by_index(
208225
source: CommentedMap, target: CommentedMap, indices: list[int], forced_update_keys: Sequence[str] = (), force_update_all: bool = False
209226
) -> None:
210227
"""
@@ -231,7 +248,7 @@ def transfer_missing_yaml_comments_by_index(
231248
target_comment[index] = source_comment[index]
232249

233250

234-
def transfer_missing_yaml_comments(
251+
def transfer_yaml_comments(
235252
source: CommentedMap,
236253
target: CommentedMap,
237254
comment_normalisation: YamlCommentNormalisation,
@@ -251,7 +268,7 @@ def transfer_missing_yaml_comments(
251268
case YamlCommentNormalisation.NONE:
252269
pass
253270
case YamlCommentNormalisation.LEADING | YamlCommentNormalisation.LEADING_WITH_CONVERSION_FROM_TRAILING:
254-
transfer_missing_yaml_comments_by_index(
271+
transfer_yaml_comments_by_index(
255272
source, target, [ITEM_COMMENT_INDEX_BEFORE], forced_update_keys=forced_update_keys, force_update_all=force_update_all
256273
)
257274
case _:

0 commit comments

Comments
 (0)