@@ -1027,6 +1027,7 @@ private File writeSketchImpl(RunnerListener listener) throws IOException {
10271027 checkForUnsupportedJavaArraySyntax (code , listener );
10281028 checkForArrayListGetValueCopy (code , listener );
10291029 checkForArrayListGetDotAccess (code , listener );
1030+ checkForJavaStaticCallSyntax (code , listener );
10301031 code = stripRawStringLiterals (code );
10311032 code = code .replaceAll ("(?<=[0-9a-fA-FxXbB])'(?=[0-9a-fA-F])" , "" );
10321033 code = javaToC (code );
@@ -2356,6 +2357,73 @@ private void checkForArrayListGetDotAccess(String code, RunnerListener listener)
23562357 }
23572358 }
23582359
2360+ // [E0006] Java static method/field call syntax: ClassName.member must be ClassName::member in C++
2361+ //
2362+ // Generalized rule: any identifier that starts with an uppercase letter followed
2363+ // by a "." and then another identifier (with optional "(") is likely a Java
2364+ // static access pattern. This covers:
2365+ // Integer.parseInt(...) -> Integer::parseInt(...)
2366+ // Math.PI -> Math::PI (or just PI)
2367+ // MyClass.CONSTANT -> MyClass::CONSTANT
2368+ // Collections.sort(...) -> Collections::sort(...) or std::sort
2369+ //
2370+ // Excluded: known instance-access patterns where the variable name
2371+ // happens to start with uppercase (e.g. PImage, PFont, PVector variables).
2372+ private void checkForJavaStaticCallSyntax (String code , RunnerListener listener ) {
2373+ List <CppLexerToken > tokens ;
2374+ try { tokens = new CppLexer (code ).tokenize (); } catch (Exception e ) { return ; }
2375+ // Types known to be used as instances (not static-only classes)
2376+ java .util .Set <String > instanceTypes = java .util .Set .of (
2377+ "PImage" , "PFont" , "PVector" , "PShape" , "PGraphics" ,
2378+ "ArrayList" , "IntList" , "FloatList" , "StringList" ,
2379+ "String" , "Array" , "Table" , "TableRow" , "JSONObject" , "JSONArray" ,
2380+ "PrintWriter" , "BufferedReader" , "XML"
2381+ );
2382+ // Definitely-static classes (always trigger E0006)
2383+ java .util .Set <String > staticClasses = java .util .Set .of (
2384+ "Integer" , "Float" , "Double" , "Long" , "Boolean" , "Character" ,
2385+ "Byte" , "Short" , "Math" , "Arrays" , "Collections" , "System" ,
2386+ "Thread" , "Runtime" , "Class" , "Objects"
2387+ );
2388+ for (int i = 0 ; i + 2 < tokens .size (); i ++) {
2389+ CppLexerToken t0 = tokens .get (i );
2390+ CppLexerToken t1 = tokens .get (i + 1 );
2391+ CppLexerToken t2 = tokens .get (i + 2 );
2392+ // Pattern: IDENTIFIER . IDENTIFIER where first IDENTIFIER starts uppercase
2393+ if (t0 .type () != CppLexerTokenType .IDENTIFIER ) continue ;
2394+ if (!t1 .isPunct ("." )) continue ;
2395+ if (t2 .type () != CppLexerTokenType .IDENTIFIER ) continue ;
2396+ String firstName = t0 .text ();
2397+ if (firstName .isEmpty () || !Character .isUpperCase (firstName .charAt (0 ))) continue ;
2398+ if (instanceTypes .contains (firstName )) continue ; // known instance type
2399+ // Only fire for known static classes OR if preceded by nothing
2400+ // (i.e. not "obj.UpperMethod()" which is a method call)
2401+ // Check context: if previous token is ")", "]", or identifier, skip
2402+ boolean preceded = i > 0 && (
2403+ tokens .get (i -1 ).isPunct (")" )
2404+ || tokens .get (i -1 ).isPunct ("]" )
2405+ || tokens .get (i -1 ).isPunct (">" )
2406+ || tokens .get (i -1 ).type () == CppLexerTokenType .IDENTIFIER );
2407+ if (preceded && !staticClasses .contains (firstName )) continue ;
2408+ // Check that next token after t2 is "(" or nothing method-like
2409+ boolean isCall = i + 3 < tokens .size () && tokens .get (i + 3 ).isPunct ("(" );
2410+ boolean isField = !isCall ; // field access like Math.PI
2411+ if (!staticClasses .contains (firstName ) && !isCall ) continue ; // only fire on known statics for field access
2412+ int line = t0 .line ();
2413+ String url = getWebsiteBaseUrl () + "/error/E0006.html" ;
2414+ String access = t2 .text () + (isCall ? "(...)" : "" );
2415+ String msg =
2416+ "\n [E0006] Java static access syntax is not valid in C++.\n " +
2417+ " Line " + line + ": \" " + firstName + "." + access + "\" \n " +
2418+ " In C++, static members use :: not .:\n " +
2419+ " " + firstName + "::" + access + "\n " +
2420+ " Reference: " + url + "\n " ;
2421+ System .err .println (msg );
2422+ listener .statusError ("E0006: use " + firstName + "::" + t2 .text () + " not . -- see console" );
2423+ throw new AlreadyReportedException ("E0006: Java static access syntax -- see console." );
2424+ }
2425+ }
2426+
23592427 private void checkForUnsupportedJavaArraySyntax (String code , RunnerListener listener ) {
23602428 try {
23612429 CppJavaArrayCheck .check (code );
0 commit comments