Avoid "uninitialized variable" message after new keyword
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Parser.java
index b7a1353..4dcd0f8 100644 (file)
@@ -14,6 +14,33 @@ import java.util.HashSet;
 import net.sourceforge.phpdt.core.compiler.CharOperation;
 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.ast.AND_AND_Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.ASTNode;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.Block;
+import net.sourceforge.phpdt.internal.compiler.ast.BreakStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ConditionalExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.ContinueStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.EqualExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldReference;
+import net.sourceforge.phpdt.internal.compiler.ast.IfStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.ast.InstanceOfExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.OR_OR_Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.OperatorIds;
+import net.sourceforge.phpdt.internal.compiler.ast.ReturnStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+import net.sourceforge.phpdt.internal.compiler.ast.StringLiteral;
+import net.sourceforge.phpdt.internal.compiler.ast.StringLiteralDQ;
+import net.sourceforge.phpdt.internal.compiler.ast.StringLiteralSQ;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
@@ -23,33 +50,6 @@ import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
 import net.sourceforge.phpdt.internal.compiler.util.Util;
 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
-import net.sourceforge.phpeclipse.internal.compiler.ast.AND_AND_Expression;
-import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
-import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
-import net.sourceforge.phpeclipse.internal.compiler.ast.BinaryExpression;
-import net.sourceforge.phpeclipse.internal.compiler.ast.Block;
-import net.sourceforge.phpeclipse.internal.compiler.ast.BreakStatement;
-import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
-import net.sourceforge.phpeclipse.internal.compiler.ast.ConditionalExpression;
-import net.sourceforge.phpeclipse.internal.compiler.ast.ContinueStatement;
-import net.sourceforge.phpeclipse.internal.compiler.ast.EqualExpression;
-import net.sourceforge.phpeclipse.internal.compiler.ast.Expression;
-import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
-import net.sourceforge.phpeclipse.internal.compiler.ast.FieldReference;
-import net.sourceforge.phpeclipse.internal.compiler.ast.IfStatement;
-import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
-import net.sourceforge.phpeclipse.internal.compiler.ast.InstanceOfExpression;
-import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
-import net.sourceforge.phpeclipse.internal.compiler.ast.OR_OR_Expression;
-import net.sourceforge.phpeclipse.internal.compiler.ast.OperatorIds;
-import net.sourceforge.phpeclipse.internal.compiler.ast.ReturnStatement;
-import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
-import net.sourceforge.phpeclipse.internal.compiler.ast.Statement;
-import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteral;
-import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralDQ;
-import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralSQ;
-import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
-import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
 import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil;
 
 import org.eclipse.core.resources.IFile;
@@ -422,6 +422,9 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
                        try {
                                statement = statement();
                                blockStatements.add(statement);
+                               if (token == TokenNameEOF) {
+                                       return null;
+                               }
                                if (branchStatement && statement != null) {
                                        // reportSyntaxError("Unreachable code", statement.sourceStart,
                                        // statement.sourceEnd);
@@ -2502,37 +2505,33 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
                        // | rw_variable T_INC
                        // | rw_variable T_DEC
                        case TokenNameIdentifier:
-                               char[] ident = scanner.getCurrentTokenSource();
-                               Expression lhsIdentifier = identifier(true, true);
-                               if (lhsIdentifier != null) {
-                                       expression = lhsIdentifier;
-                               }
-                               if (token == TokenNameEQUAL || token == TokenNamePLUS_EQUAL
-                                               || token == TokenNameMINUS_EQUAL || token == TokenNameMULTIPLY_EQUAL || token == TokenNameDIVIDE_EQUAL
-                                               || token == TokenNameDOT_EQUAL || token == TokenNameREMAINDER_EQUAL || token == TokenNameAND_EQUAL
-                                               || token == TokenNameOR_EQUAL || token == TokenNameXOR_EQUAL || token == TokenNameRIGHT_SHIFT_EQUAL
-                                               || token == TokenNameLEFT_SHIFT_EQUAL) {
-                                       String error = "Assignment operator '"+scanner.toStringAction(token)+"' not allowed after identifier '"+new String(ident)+"' (use 'define(...)' to define constants).";
-                                       throwSyntaxError(error);
-                               }
-                               break;
                        case TokenNameVariable:
                        case TokenNameDOLLAR:
+                               Expression lhs = null;
                                boolean rememberedVar = false;
-                               Expression lhs = variable(true, true);
-                               if (lhs != null && lhs instanceof FieldReference && token != TokenNameEQUAL && token != TokenNamePLUS_EQUAL
-                                               && token != TokenNameMINUS_EQUAL && token != TokenNameMULTIPLY_EQUAL && token != TokenNameDIVIDE_EQUAL
-                                               && token != TokenNameDOT_EQUAL && token != TokenNameREMAINDER_EQUAL && token != TokenNameAND_EQUAL
-                                               && token != TokenNameOR_EQUAL && token != TokenNameXOR_EQUAL && token != TokenNameRIGHT_SHIFT_EQUAL
-                                               && token != TokenNameLEFT_SHIFT_EQUAL) {
-                                       FieldReference ref = (FieldReference) lhs;
-                                       if (!containsVariableSet(ref.token)) {
-                                               problemReporter.uninitializedLocalVariable(new String(ref.token), ref.sourceStart(), ref.sourceEnd(), referenceContext,
-                                                               compilationUnit.compilationResult);
-                                               addVariableSet(ref.token);
+                               if (token == TokenNameIdentifier) {
+                                       lhs = identifier(true, true);
+                                       if (lhs != null) {
+                                               expression = lhs;
+                                       }
+                               } else {
+                                       lhs = variable(true, true);
+                                       if (lhs != null) {
+                                               expression = lhs;
+                                       }
+                                       if (lhs != null && lhs instanceof FieldReference && token != TokenNameEQUAL && token != TokenNamePLUS_EQUAL
+                                                       && token != TokenNameMINUS_EQUAL && token != TokenNameMULTIPLY_EQUAL && token != TokenNameDIVIDE_EQUAL
+                                                       && token != TokenNameDOT_EQUAL && token != TokenNameREMAINDER_EQUAL && token != TokenNameAND_EQUAL
+                                                       && token != TokenNameOR_EQUAL && token != TokenNameXOR_EQUAL && token != TokenNameRIGHT_SHIFT_EQUAL
+                                                       && token != TokenNameLEFT_SHIFT_EQUAL) {
+                                               FieldReference ref = (FieldReference) lhs;
+                                               if (!containsVariableSet(ref.token)) {
+                                                       problemReporter.uninitializedLocalVariable(new String(ref.token), ref.sourceStart(), ref.sourceEnd(),
+                                                                       referenceContext, compilationUnit.compilationResult);
+                                                       addVariableSet(ref.token);
+                                               }
                                        }
                                }
-
                                switch (token) {
                                case TokenNameEQUAL:
                                        if (lhs != null && lhs instanceof FieldReference) {
@@ -2788,7 +2787,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
                if (Scanner.TRACE) {
                        System.out.println("TRACE: dynamic_class_name_reference()");
                }
-               base_variable();
+               base_variable(true);
                if (token == TokenNameMINUS_GREATER) {
                        getNextToken();
                        object_property();
@@ -3014,26 +3013,24 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
                                        }
                                }
                        }
-                       // TODO is this ok ?
-                       return ref;
-                       // throwSyntaxError("'(' expected in function call.");
-               }
-               getNextToken();
-               if (token == TokenNameRPAREN) {
+               } else {
                        getNextToken();
-                       return ref;
-               }
-               non_empty_function_call_parameter_list();
-               if (token != TokenNameRPAREN) {
-                       String functionName;
-                       if (ident == null) {
-                               functionName = new String(" ");
-                       } else {
-                               functionName = new String(ident);
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                               return ref;
+                       }
+                       non_empty_function_call_parameter_list();
+                       if (token != TokenNameRPAREN) {
+                               String functionName;
+                               if (ident == null) {
+                                       functionName = new String(" ");
+                               } else {
+                                       functionName = new String(ident);
+                               }
+                               throwSyntaxError("')' expected in function call (" + functionName + ").");
                        }
-                       throwSyntaxError("')' expected in function call (" + functionName + ").");
+                       getNextToken();
                }
-               getNextToken();
                return ref;
        }
 
@@ -3106,7 +3103,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
                return function_call(lefthandside, ignoreVar);
        }
 
-       private Expression base_variable() {
+       private Expression base_variable(boolean lefthandside) {
                // base_variable:
                // reference_variable
                // | simple_indirect_reference reference_variable
@@ -3121,7 +3118,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
                        while (token == TokenNameDOLLAR) {
                                getNextToken();
                        }
-                       reference_variable(false, false);
+                       reference_variable(lefthandside, false);
                }
                return ref;
        }
@@ -3349,7 +3346,113 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
                // base_variable_with_function_calls T_OBJECT_OPERATOR
                // object_property method_or_not variable_properties
                // | base_variable_with_function_calls
-               return base_variable_with_function_calls(lefthandside, ignoreVar);
+
+               // Expression ref = function_call(lefthandside, ignoreVar);
+
+               // function_call:
+               // T_STRING '(' function_call_parameter_list ')'
+               // | class_constant '(' function_call_parameter_list ')'
+               // | static_member '(' function_call_parameter_list ')'
+               // | variable_without_objects '(' function_call_parameter_list ')'
+               char[] defineName = null;
+               char[] ident = null;
+               int startPos = 0;
+               int endPos = 0;
+               Expression ref = null;
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: function_call()");
+               }
+               if (token == TokenNameIdentifier) {
+                       ident = scanner.getCurrentIdentifierSource();
+                       defineName = ident;
+                       startPos = scanner.getCurrentTokenStartPosition();
+                       endPos = scanner.getCurrentTokenEndPosition();
+                       getNextToken();
+
+                       if (token == TokenNameEQUAL || token == TokenNamePLUS_EQUAL || token == TokenNameMINUS_EQUAL
+                                       || token == TokenNameMULTIPLY_EQUAL || token == TokenNameDIVIDE_EQUAL || token == TokenNameDOT_EQUAL
+                                       || token == TokenNameREMAINDER_EQUAL || token == TokenNameAND_EQUAL || token == TokenNameOR_EQUAL
+                                       || token == TokenNameXOR_EQUAL || token == TokenNameRIGHT_SHIFT_EQUAL || token == TokenNameLEFT_SHIFT_EQUAL) {
+                               String error = "Assignment operator '" + scanner.toStringAction(token) + "' not allowed after identifier '"
+                                               + new String(ident) + "' (use 'define(...)' to define constants).";
+                               reportSyntaxError(error);
+                       }
+
+                       switch (token) {
+                       case TokenNamePAAMAYIM_NEKUDOTAYIM:
+                               // static member:
+                               defineName = null;
+                               getNextToken();
+                               if (token == TokenNameIdentifier) {
+                                       // class _constant
+                                       getNextToken();
+                               } else {
+                                       // static member:
+                                       variable_without_objects(true, false);
+                               }
+                               break;
+                       }
+               } else {
+                       ref = variable_without_objects(lefthandside, ignoreVar);
+               }
+               if (token != TokenNameLPAREN) {
+                       if (defineName != null) {
+                               // does this identifier contain only uppercase characters?
+                               if (defineName.length == 3) {
+                                       if (defineName[0] == 'd' && defineName[1] == 'i' && defineName[2] == 'e') {
+                                               defineName = null;
+                                       }
+                               } else if (defineName.length == 4) {
+                                       if (defineName[0] == 't' && defineName[1] == 'r' && defineName[2] == 'u' && defineName[3] == 'e') {
+                                               defineName = null;
+                                       } else if (defineName[0] == 'n' && defineName[1] == 'u' && defineName[2] == 'l' && defineName[3] == 'l') {
+                                               defineName = null;
+                                       }
+                               } else if (defineName.length == 5) {
+                                       if (defineName[0] == 'f' && defineName[1] == 'a' && defineName[2] == 'l' && defineName[3] == 's' && defineName[4] == 'e') {
+                                               defineName = null;
+                                       }
+                               }
+                               if (defineName != null) {
+                                       for (int i = 0; i < defineName.length; i++) {
+                                               if (Character.isLowerCase(defineName[i])) {
+                                                       problemReporter.phpUppercaseIdentifierWarning(startPos, endPos, referenceContext, compilationUnit.compilationResult);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       // TODO is this ok ?
+                       // return ref;
+                       // throwSyntaxError("'(' expected in function call.");
+               } else {
+                       getNextToken();
+
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                               ref = null;
+                       } else {
+                               non_empty_function_call_parameter_list();
+                               if (token != TokenNameRPAREN) {
+                                       String functionName;
+                                       if (ident == null) {
+                                               functionName = new String(" ");
+                                       } else {
+                                               functionName = new String(ident);
+                                       }
+                                       throwSyntaxError("')' expected in function call (" + functionName + ").");
+                               }
+                               getNextToken();
+                       }
+               }
+               if (token == TokenNameMINUS_GREATER) {
+                       ref = null;
+                       getNextToken();
+                       object_property();
+                       method_or_not();
+                       variable_properties();
+               }
+               return ref;
        }
 
        private void method_or_not() {