@@ -272,45 +272,54 @@ private void highlightVariableReferences(List<Mark> marks) {
272272 String name = m .group (1 );
273273 int position = m .start (1 );
274274
275- // Skip known keywords and types
275+ // Skip known keywords
276276 if (knownIdentifiers .contains (name )) continue ;
277-
278- // Skip type names (first letter uppercase)
279- if (Character .isUpperCase (name .charAt (0 ))) continue ;
280-
277+
281278 // Skip field access (identifier preceded by a dot) - these should be gray/default
282- // e.g., in "container.lines", the "lines" part should not be marked
283279 if (isFieldAccess (position )) continue ;
284280
285281 // Never treat parts of import/package statements as undefined variables
286- // (otherwise the first package segment like "noppes" gets marked red and overrides import highlighting)
287282 if (isInImportOrPackageStatement (position )) continue ;
288-
283+
289284 // Check if inside a method
290285 MethodBlock methodBlock = findMethodBlockAtPosition (position );
291-
286+
292287 if (methodBlock != null ) {
293- // Inside a method - check in order: parameter, local (position-aware), global
288+ // Inside a method - first check parameters, locals, and globals (respecting registrations)
294289 if (methodBlock .parameters .contains (name )) {
295290 marks .add (new Mark (m .start (1 ), m .end (1 ), TokenType .PARAMETER ));
296- } else if (methodBlock .isLocalDeclaredAtPosition (name , position )) {
297- // Local variable is declared at or before this position
291+ continue ;
292+ }
293+
294+ if (methodBlock .isLocalDeclaredAtPosition (name , position ) || localFields .contains (name )) {
298295 marks .add (new Mark (m .start (1 ), m .end (1 ), TokenType .LOCAL_FIELD ));
299- } else if (globalFields .contains (name )) {
296+ continue ;
297+ }
298+
299+ if (globalFields .contains (name )) {
300300 marks .add (new Mark (m .start (1 ), m .end (1 ), TokenType .GLOBAL_FIELD ));
301- } else {
302- // Unknown variable - mark as undefined (Bug 11)
303- // But only if it looks like a variable reference (not a method call)
304- if (!isMethodCall (position ) && !isTypeReference (name , position )) {
305- marks .add (new Mark (m .start (1 ), m .end (1 ), TokenType .UNDEFINED_VAR ));
306- }
301+ continue ;
302+ }
303+
304+ // If it's an uppercase identifier that hasn't been registered as a local/param/global,
305+ // treat it as a type reference (skip) rather than an undefined variable.
306+ if (Character .isUpperCase (name .charAt (0 ))) continue ;
307+
308+ // Unknown variable - mark as undefined but only if it's not a method call or type reference
309+ if (!isMethodCall (position ) && !isTypeReference (name , position )) {
310+ marks .add (new Mark (m .start (1 ), m .end (1 ), TokenType .UNDEFINED_VAR ));
307311 }
308312 } else {
309- // Outside any method - check global fields
310- if (globalFields .contains (name )) {
313+ // Outside any method - check global fields first
314+ if (globalFields .contains (name ) || localFields . contains ( name ) ) {
311315 marks .add (new Mark (m .start (1 ), m .end (1 ), TokenType .GLOBAL_FIELD ));
312- } else if (!isMethodCall (position ) && !isTypeReference (name , position )) {
313- // Mark as undefined if it's not a method call or type reference
316+ continue ;
317+ }
318+
319+ // Uppercase unregistered identifiers are likely type names; skip them
320+ if (Character .isUpperCase (name .charAt (0 ))) continue ;
321+
322+ if (!isMethodCall (position ) && !isTypeReference (name , position )) {
314323 marks .add (new Mark (m .start (1 ), m .end (1 ), TokenType .UNDEFINED_VAR ));
315324 }
316325 }
@@ -805,6 +814,32 @@ private void collectTypeDeclarations(List<Mark> marks) {
805814 int contentStart = lineStart + genericStart + 1 ;
806815 highlightGenericTypes (genericContent , contentStart , marks , excluded );
807816 }
817+
818+ // If followed by a variable name, detect it and register uppercase-starting
819+ // variable names as locals so subsequent identifier scanning treats them
820+ // as variables (not types). This handles declarations like:
821+ // MyType Capital = new MyType();
822+ if (followedByVarName ) {
823+ int v = posAfterType ;
824+ // skip whitespace
825+ while (v < s .length () && Character .isWhitespace (s .charAt (v ))) v ++;
826+ int varStart = v ;
827+ while (v < s .length () && (Character .isLetterOrDigit (s .charAt (v )) || s .charAt (v ) == '_' )) v ++;
828+ int varEnd = v ;
829+ if (varEnd > varStart ) {
830+ String varName = s .substring (varStart , varEnd );
831+ int absVarStart = lineStart + varStart ;
832+ int absVarEnd = lineStart + varEnd ;
833+ if (Character .isUpperCase (varName .charAt (0 ))) {
834+ MethodBlock mb = findMethodBlockAtPosition (absVarStart );
835+ if (mb != null ) {
836+ if (!mb .localVariables .contains (varName )) mb .localVariables .add (varName );
837+ if (!localFields .contains (varName )) localFields .add (varName );
838+ marks .add (new Mark (absVarStart , absVarEnd , TokenType .LOCAL_FIELD ));
839+ }
840+ }
841+ }
842+ }
808843 }
809844
810845 searchFrom = m .end ();
0 commit comments