@@ -34,12 +34,20 @@ export class DclTile implements IDclContainer {
3434 return false ;
3535 }
3636
37+ get isNumber ( ) : boolean {
38+ return false ;
39+ }
40+
3741 get range ( ) : Range {
3842 const begin = this . firstAtom . range . start ;
3943 const close = this . lastAtom . range . end ;
4044 return new Range ( begin , close ) ;
4145 }
4246
47+ get rank ( ) : number {
48+ return this . line * 1000 + this . column ;
49+ }
50+
4351 equal ( atom : IDclFragment ) : boolean {
4452 return JSON . stringify ( this ) === JSON . stringify ( atom ) ;
4553 }
@@ -88,12 +96,27 @@ export class DclTile implements IDclContainer {
8896 return null ;
8997 }
9098
99+ get isWellFormed ( ) : boolean {
100+ if ( this . length === 2 ) {
101+ return / ^ [ a - z \_ ] + $ / i. test ( this . firstAtom . symbol ) && this . lastAtom . symbol === ';' ;
102+ }
103+
104+ const name = this . tileTypeAtom ?. symbol . toLowerCase ( ) ?? '' ;
105+
106+ return this . firstAtom ?. symbol === ':'
107+ && this . closeBracketAtom ?. symbol === '}'
108+ && / ^ [ a - z \_ ] + $ / i. test ( name )
109+ && this . openBracketAtom ?. symbol === '{' ; // doing this one last because it loops over all atoms
110+ }
111+
91112 getParentFrom ( position : Position | IDclFragment , tilesOnly = false ) : IDclContainer {
92113 const pos = position instanceof Position ? position : position . range . start ;
93114 if ( this . contains ( pos ) ) {
115+ let failed = 0 ;
94116 for ( let i = 0 ; i < this . length ; i ++ ) {
95117 const dclObj = this . atoms [ i ] ;
96118 if ( ! dclObj . contains ( pos ) ) {
119+ failed ++ ;
97120 continue ;
98121 }
99122 if ( dclObj instanceof DclAttribute ) {
@@ -104,7 +127,40 @@ export class DclTile implements IDclContainer {
104127 return dclObj . asTile . getParentFrom ( pos , tilesOnly ) ?? this ;
105128 }
106129 }
130+ if ( failed === this . length ) {
131+ return this ; // position is not at the location of an atom, but we only care about the parent anyway
132+ }
133+ }
134+ return null ;
135+ }
136+
137+ getImpliedParent ( position : Position ) : IDclContainer {
138+ // Note: attributes handle themselves, your challange is determining if an attribute is malformed and needs a force return.
139+ let prev = 0 ;
140+ const positionRank = position . line * 1000 + position . character ;
141+ for ( let i = 0 ; i < this . atoms . length ; i ++ ) {
142+ const atom = this . atoms [ i ] ;
143+ if ( prev > 0 && positionRank > prev && positionRank < atom . rank ) {
144+ return this . atoms [ i - 1 ] . asContainer ?? this ;
145+ }
146+
147+ const contains = atom . range . contains ( position ) ;
148+ if ( atom instanceof DclAtom ) {
149+ if ( contains ) {
150+ return this ;
151+ }
152+ prev = atom . rank ;
153+ continue ;
154+ }
155+
156+ if ( contains ) {
157+ // if the container is an attribute it will return itself, if its a tile it will keep digging for the best scenario
158+ return atom . asContainer . getImpliedParent ( position ) ?? this ;
159+ }
160+
161+ prev = atom . rank ;
107162 }
163+
108164 return null ;
109165 }
110166
0 commit comments