fix $76 add support for enum constants highlighting and initial enum documentation
This commit is contained in:
parent
84f2f8fac4
commit
65a7555e93
74
docs/OOP.md
74
docs/OOP.md
@ -168,6 +168,80 @@ Compatibility notes:
|
||||
|
||||
Earlier drafts and docs described a declaration‑order depth‑first linearization. Lyng now uses C3 MRO for member lookup and disambiguation. Most code should continue to work unchanged, but in rare edge cases involving diamonds or complex multiple inheritance, the chosen base for an ambiguous member may change to reflect C3. If needed, disambiguate explicitly using `this@Type.member(...)` inside class bodies or casts `(expr as Type).member(...)` from outside.
|
||||
|
||||
## Enums
|
||||
|
||||
Lyng provides lightweight enums for representing a fixed set of named constants. Enums are classes whose instances are predefined and singletons.
|
||||
|
||||
Current syntax supports simple enum declarations with just entry names:
|
||||
|
||||
enum Color {
|
||||
RED, GREEN, BLUE
|
||||
}
|
||||
|
||||
Usage:
|
||||
|
||||
- Type of entries: every entry is an instance of its enum type.
|
||||
|
||||
assert( Color.RED is Color )
|
||||
|
||||
- Order and names: each entry has zero‑based `ordinal` and string `name`.
|
||||
|
||||
assertEquals(0, Color.RED.ordinal)
|
||||
assertEquals("BLUE", Color.BLUE.name)
|
||||
|
||||
- All entries as a list in declaration order: `EnumType.entries`.
|
||||
|
||||
assertEquals([Color.RED, Color.GREEN, Color.BLUE], Color.entries)
|
||||
|
||||
- Lookup by name: `EnumType.valueOf("NAME")` → entry.
|
||||
|
||||
assertEquals(Color.GREEN, Color.valueOf("GREEN"))
|
||||
|
||||
- Equality and comparison:
|
||||
- Equality uses identity of entries, e.g., `Color.RED == Color.valueOf("RED")`.
|
||||
- Cross‑enum comparisons are not allowed.
|
||||
- Ordering comparisons use `ordinal`.
|
||||
|
||||
assert( Color.RED == Color.valueOf("RED") )
|
||||
assert( Color.RED.ordinal < Color.BLUE.ordinal )
|
||||
>>> void
|
||||
|
||||
### Enums with `when`
|
||||
|
||||
Use `when(subject)` with equality branches for enums. See full `when` guide: [The `when` statement](when.md).
|
||||
|
||||
enum Color { RED, GREEN, BLUE }
|
||||
|
||||
fun describe(c) {
|
||||
when(c) {
|
||||
Color.RED, Color.GREEN -> "primary-like"
|
||||
Color.BLUE -> "blue"
|
||||
else -> "unknown" // if you pass something that is not a Color
|
||||
}
|
||||
}
|
||||
assertEquals("primary-like", describe(Color.RED))
|
||||
assertEquals("blue", describe(Color.BLUE))
|
||||
>>> void
|
||||
|
||||
### Serialization
|
||||
|
||||
Enums are serialized compactly with Lynon: the encoded value stores just the entry ordinal within the enum type, which is both space‑efficient and fast.
|
||||
|
||||
import lyng.serialization
|
||||
|
||||
enum Color { RED, GREEN, BLUE }
|
||||
|
||||
val e = Lynon.encode(Color.BLUE)
|
||||
val decoded = Lynon.decode(e)
|
||||
assertEquals(Color.BLUE, decoded)
|
||||
>>> void
|
||||
|
||||
Notes and limitations (current version):
|
||||
|
||||
- Enum declarations support only simple entry lists: no per‑entry bodies, no custom constructors, and no user‑defined methods/fields on the enum itself yet.
|
||||
- `name` and `ordinal` are read‑only properties of an entry.
|
||||
- `entries` is a read‑only list owned by the enum type.
|
||||
|
||||
## fields and visibility
|
||||
|
||||
It is possible to add non-constructor fields:
|
||||
|
||||
@ -66,6 +66,26 @@ You can use blocks in if statement, as expected:
|
||||
limited
|
||||
>>> 120.0
|
||||
|
||||
## Enums (quick intro)
|
||||
|
||||
Lyng supports simple enums for a fixed set of named constants. Declare with `enum Name { ... }` and use entries as `Name.ENTRY`.
|
||||
|
||||
enum Color {
|
||||
RED, GREEN, BLUE
|
||||
}
|
||||
|
||||
assert( Color.RED is Color )
|
||||
assertEquals( 0, Color.RED.ordinal )
|
||||
assertEquals( "BLUE", Color.BLUE.name )
|
||||
|
||||
// All entries as a list, in order:
|
||||
assertEquals( [Color.RED, Color.GREEN, Color.BLUE], Color.entries )
|
||||
|
||||
// Lookup by name:
|
||||
assertEquals( Color.GREEN, Color.valueOf("GREEN") )
|
||||
|
||||
For more details (usage patterns, `when` switching, serialization), see OOP notes: [Enums in detail](OOP.md#enums).
|
||||
|
||||
When putting multiple statments in the same line it is convenient and recommended to use `;`:
|
||||
|
||||
var from; var to
|
||||
|
||||
@ -262,6 +262,18 @@ class LyngExternalAnnotator : ExternalAnnotator<LyngExternalAnnotator.Input, Lyn
|
||||
}
|
||||
}
|
||||
|
||||
// Map Enum constants from token highlighter to IDEA enum constant color
|
||||
run {
|
||||
val tokens = try { SimpleLyngHighlighter().highlight(text) } catch (_: Throwable) { emptyList() }
|
||||
for (s in tokens) if (s.kind == HighlightKind.EnumConstant) {
|
||||
val start = s.range.start
|
||||
val end = s.range.endExclusive
|
||||
if (start in 0..end && end <= text.length && start < end) {
|
||||
putRange(start, end, LyngHighlighterColors.ENUM_CONSTANT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build spell index payload: identifiers from symbols + references; comments/strings from simple highlighter
|
||||
val idRanges = mutableSetOf<IntRange>()
|
||||
try {
|
||||
|
||||
@ -65,6 +65,7 @@ class LyngColorSettingsPage : ColorSettingsPage {
|
||||
AttributesDescriptor("Type (semantic)", LyngHighlighterColors.TYPE),
|
||||
AttributesDescriptor("Namespace (semantic)", LyngHighlighterColors.NAMESPACE),
|
||||
AttributesDescriptor("Parameter (semantic)", LyngHighlighterColors.PARAMETER),
|
||||
AttributesDescriptor("Enum constant (semantic)", LyngHighlighterColors.ENUM_CONSTANT),
|
||||
)
|
||||
|
||||
override fun getColorDescriptors(): Array<ColorDescriptor> = ColorDescriptor.EMPTY_ARRAY
|
||||
|
||||
@ -77,4 +77,9 @@ object LyngHighlighterColors {
|
||||
val ANNOTATION: TextAttributesKey = TextAttributesKey.createTextAttributesKey(
|
||||
"LYNG_ANNOTATION", DefaultLanguageHighlighterColors.METADATA
|
||||
)
|
||||
|
||||
// Enum constant (declaration or usage)
|
||||
val ENUM_CONSTANT: TextAttributesKey = TextAttributesKey.createTextAttributesKey(
|
||||
"LYNG_ENUM_CONSTANT", DefaultLanguageHighlighterColors.STATIC_FIELD
|
||||
)
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ object SiteHighlightLocal {
|
||||
HighlightKind.Label -> "hl-lbl"
|
||||
HighlightKind.Directive -> "hl-dir"
|
||||
HighlightKind.Error -> "hl-err"
|
||||
HighlightKind.EnumConstant -> "hl-enumc"
|
||||
}
|
||||
|
||||
private fun htmlEscape(s: String): String = buildString(s.length) {
|
||||
|
||||
@ -117,6 +117,7 @@
|
||||
.hl-class { color: #5a32a3; font-weight: 600; }
|
||||
.hl-val { color: #1b7f5a; }
|
||||
.hl-var { color: #1b7f5a; text-decoration: underline dotted currentColor; }
|
||||
.hl-enumc { color: #b08800; font-weight: 600; }
|
||||
.hl-param { color: #0969da; font-style: italic; }
|
||||
.hl-num { color: #005cc5; }
|
||||
.hl-str { color: #032f62; }
|
||||
@ -139,6 +140,7 @@
|
||||
[data-bs-theme="dark"] .hl-class{ color: #d2a8ff; font-weight: 700; }
|
||||
[data-bs-theme="dark"] .hl-val { color: #7ee787; }
|
||||
[data-bs-theme="dark"] .hl-var { color: #7ee787; text-decoration: underline dotted currentColor; }
|
||||
[data-bs-theme="dark"] .hl-enumc{ color: #f2cc60; font-weight: 700; }
|
||||
[data-bs-theme="dark"] .hl-param{ color: #a5d6ff; font-style: italic; }
|
||||
[data-bs-theme="dark"] .hl-num { color: #79c0ff; }
|
||||
[data-bs-theme="dark"] .hl-str,
|
||||
@ -156,7 +158,7 @@
|
||||
z-index: 1020; /* above content, below navbar */
|
||||
top: var(--navbar-offset, 56px);
|
||||
left: 0;
|
||||
width: 162px; /* 10% narrower than 180px */
|
||||
width: 242px; /* 10% narrower than 180px */
|
||||
text-align: center;
|
||||
/* Slightly asymmetric padding to visually center text within rotated band (desktop) */
|
||||
/* Nudge text a bit lower on large screens */
|
||||
@ -171,9 +173,9 @@
|
||||
}
|
||||
@media (max-width: 576px) {
|
||||
.corner-ribbon {
|
||||
width: 135px; /* 10% narrower than 150px */
|
||||
width: 195px; /* 10% narrower than 150px */
|
||||
transform: translate(-50px, 8px) rotate(-45deg);
|
||||
font-size: .7rem; /* even smaller on phones */
|
||||
font-size: .6rem; /* even smaller on phones */
|
||||
padding: .32rem 0 .28rem; /* keep mobile text centered too */
|
||||
}
|
||||
}
|
||||
@ -182,8 +184,8 @@
|
||||
<body>
|
||||
<!-- Top-left version ribbon -->
|
||||
<div class="corner-ribbon bg-danger text-white">
|
||||
<span class="me-3">
|
||||
v1.0.3
|
||||
<span style="margin-left: -5em">
|
||||
v1.0.6-SNAPSHOT
|
||||
</span>
|
||||
</div>
|
||||
<!-- Fixed top navbar for the whole site -->
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user