X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java index 908fbf8..d3e2a3c 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java @@ -9,6 +9,8 @@ package net.sourceforge.phpdt.internal.compiler.parser; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.Stack; import net.sourceforge.phpdt.core.compiler.CharOperation; import net.sourceforge.phpdt.core.compiler.ITerminalSymbols; @@ -308,6 +310,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI */ public void parse(String s, HashMap variables) { fMethodVariables = variables; + fStackUnassigned = new Stack(); init(s); parse(); } @@ -470,8 +473,10 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI try { statement = statement(); blockStatements.add(statement); - if (branchStatement && statement!=null) { - reportSyntaxError("Unreachable code", statement.sourceStart, statement.sourceEnd); + if (branchStatement && statement != null) { +// reportSyntaxError("Unreachable code", statement.sourceStart, statement.sourceEnd); + problemReporter.unreachableCode(new String(scanner.getCurrentIdentifierSource()),statement.sourceStart, statement.sourceEnd, + referenceContext, compilationUnit.compilationResult); } if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse) || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor) @@ -525,7 +530,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI private boolean checkUnreachableStatements(Statement statement) { if (statement instanceof ReturnStatement || statement instanceof ContinueStatement || statement instanceof BreakStatement) { return true; - } else if (statement instanceof IfStatement && ((IfStatement)statement).checkUnreachable) { + } else if (statement instanceof IfStatement && ((IfStatement) statement).checkUnreachable) { return true; } return false; @@ -718,7 +723,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI foreach_optional_arg(); if (token == TokenNameEQUAL_GREATER) { getNextToken(); - variable(); + variable(false); } if (token == TokenNameRPAREN) { getNextToken(); @@ -1059,7 +1064,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI if (token == TokenNameAND) { getNextToken(); } - w_variable(); + w_variable(true); } private void foreach_optional_arg() { @@ -1075,8 +1080,9 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI // global_var_list: // global_var_list ',' global_var //| global_var + HashSet set = peekVariableSet(); while (true) { - global_var(); + global_var(set); if (token != TokenNameCOMMA) { break; } @@ -1084,16 +1090,17 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI } } - private void global_var() { + private void global_var(HashSet set) { //global_var: // T_VARIABLE //| '$' r_variable //| '$' '{' expr '}' if (token == TokenNameVariable) { - VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_GLOBAL_VAR); if (fMethodVariables != null) { + VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_GLOBAL_VAR); fMethodVariables.put(new String(scanner.getCurrentIdentifierSource()), info); } + addVariableSet(set); getNextToken(); } else if (token == TokenNameDOLLAR) { getNextToken(); @@ -1115,13 +1122,15 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI // static_var_list ',' T_VARIABLE //| static_var_list ',' T_VARIABLE '=' static_scalar //| T_VARIABLE - //| T_VARIABLE '=' static_scalar + //| T_VARIABLE '=' static_scalar, + HashSet set = peekVariableSet(); while (true) { if (token == TokenNameVariable) { - VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_STATIC_VAR); if (fMethodVariables != null) { + VariableInfo info = new VariableInfo(scanner.getCurrentTokenStartPosition(), VariableInfo.LEVEL_STATIC_VAR); fMethodVariables.put(new String(scanner.getCurrentIdentifierSource()), info); - } + } + addVariableSet(set); getNextToken(); if (token == TokenNameEQUAL) { getNextToken(); @@ -1144,7 +1153,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI // unset_variable: // variable while (true) { - variable(); + variable(false); if (token != TokenNameCOMMA) { break; } @@ -1607,15 +1616,20 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI } } } - functionDeclarator(methodDecl); - if (token == TokenNameSEMICOLON) { - if (!isAbstract) { - throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector)); + try { + pushVariableSet(); + functionDeclarator(methodDecl); + if (token == TokenNameSEMICOLON) { + if (!isAbstract) { + throwSyntaxError("Body declaration expected for method: " + new String(methodDecl.selector)); + } + getNextToken(); + return; } - getNextToken(); - return; + functionBody(methodDecl); + } finally { + fStackUnassigned.pop(); } - functionBody(methodDecl); } private void functionDeclarator(MethodDeclaration methodDecl) { @@ -1672,6 +1686,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI // static_scalar char[] typeIdentifier = null; if (token == TokenNameIdentifier || token == TokenNameVariable || token == TokenNameAND) { + HashSet set = peekVariableSet(); while (true) { if (token == TokenNameIdentifier) { typeIdentifier = scanner.getCurrentIdentifierSource(); @@ -1691,6 +1706,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI info.typeIdentifier = typeIdentifier; fMethodVariables.put(new String(scanner.getCurrentIdentifierSource()), info); } + addVariableSet(set); getNextToken(); if (token == TokenNameEQUAL) { getNextToken(); @@ -1799,7 +1815,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI checkUnreachable(iState, b); if (token == TokenNameelseif) { new_elseif_list(iState); - } + } new_else_single(iState); if (token != TokenNameendif) { throwSyntaxError("'endif' expected."); @@ -1943,14 +1959,14 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI int off = b.statements.length - 1; if (!(b.statements[off] instanceof ReturnStatement) && !(b.statements[off] instanceof ContinueStatement) && !(b.statements[off] instanceof BreakStatement)) { - if (!(b.statements[off] instanceof IfStatement) || !((IfStatement)b.statements[off]).checkUnreachable) { + if (!(b.statements[off] instanceof IfStatement) || !((IfStatement) b.statements[off]).checkUnreachable) { iState.checkUnreachable = false; } - } + } } } else { if (!(s instanceof ReturnStatement) && !(s instanceof ContinueStatement) && !(s instanceof BreakStatement)) { - if (!(s instanceof IfStatement) || !((IfStatement)s).checkUnreachable) { + if (!(s instanceof IfStatement) || !((IfStatement) s).checkUnreachable) { iState.checkUnreachable = false; } } @@ -2420,9 +2436,17 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI case TokenNameVariable: case TokenNameDOLLAR: boolean rememberedVar = false; - Expression lhs = variable(); +// char[] lhsVar = null; +// if (token==TokenNameVariable) { +// lhsVar = scanner.getCurrentTokenSource(); +// } + Expression lhs = variable(true); + switch (token) { case TokenNameEQUAL: +// if (lhsVar != null) { +// addVariableSet(lhsVar); +// } getNextToken(); if (token == TokenNameAND) { getNextToken(); @@ -2446,7 +2470,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI } } } else { - Expression rhs = variable(); + Expression rhs = variable(false); if (rhs != null && rhs instanceof FieldReference && lhs != null && lhs instanceof FieldReference) { // example: // $var = &$ref; @@ -2734,8 +2758,10 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI // variable //| T_LIST '(' assignment_list ')' //| /* empty */ - if (token == TokenNameVariable || token == TokenNameDOLLAR) { - variable(); + if (token == TokenNameVariable) { + variable(true); + } else if (token == TokenNameDOLLAR) { + variable(false); } else { if (token == TokenNamelist) { getNextToken(); @@ -2776,17 +2802,17 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI while (true) { if (token == TokenNameAND) { getNextToken(); - variable(); + variable(false); } else { expr(); if (token == TokenNameAND) { getNextToken(); - variable(); + variable(false); } else if (token == TokenNameEQUAL_GREATER) { getNextToken(); if (token == TokenNameAND) { getNextToken(); - variable(); + variable(false); } else { expr(); } @@ -2812,7 +2838,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI // } // } while (true); // } - private Expression variable_without_objects() { + private Expression variable_without_objects(boolean lefthandside) { // variable_without_objects: // reference_variable // | simple_indirect_reference reference_variable @@ -2822,10 +2848,10 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI while (token == TokenNameDOLLAR) { getNextToken(); } - return reference_variable(); + return reference_variable(lefthandside); } - private Expression function_call() { + private Expression function_call(boolean lefthandside) { // function_call: // T_STRING '(' function_call_parameter_list ')' //| class_constant '(' function_call_parameter_list ')' @@ -2855,12 +2881,12 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI getNextToken(); } else { // static member: - variable_without_objects(); + variable_without_objects(false); } break; } } else { - ref = variable_without_objects(); + ref = variable_without_objects(lefthandside); } if (token != TokenNameLPAREN) { if (defineName != null) { @@ -2931,7 +2957,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI while (true) { if (token == TokenNameAND) { getNextToken(); - w_variable(); + w_variable(false); } else { // if (token == TokenNameIdentifier || token == // TokenNameVariable @@ -2968,10 +2994,10 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI throwSyntaxError("'::' expected after class name (static_member)."); } getNextToken(); - variable_without_objects(); + variable_without_objects(false); } - private Expression base_variable_with_function_calls() { + private Expression base_variable_with_function_calls(boolean lefthandside) { // base_variable_with_function_calls: // base_variable //| function_call @@ -2993,7 +3019,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI // scanner.phpMode = true; // } // if (functionCall) { - return function_call(); + return function_call(lefthandside); // } else { // base_variable(); // } @@ -3014,7 +3040,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI while (token == TokenNameDOLLAR) { getNextToken(); } - reference_variable(); + reference_variable(false); } return ref; } @@ -3024,7 +3050,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI // // '$' // //| simple_indirect_reference '$' // } - private Expression reference_variable() { + private Expression reference_variable(boolean lefthandside) { // reference_variable: // reference_variable '[' dim_offset ']' // | reference_variable '{' expr '}' @@ -3033,7 +3059,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI if (Scanner.TRACE) { System.out.println("TRACE: reference_variable()"); } - ref = compound_variable(); + ref = compound_variable(lefthandside); while (true) { if (token == TokenNameLBRACE) { ref = null; @@ -3061,7 +3087,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI return ref; } - private Expression compound_variable() { + private Expression compound_variable(boolean lefthandside) { // compound_variable: // T_VARIABLE // | '$' '{' expr '}' @@ -3069,6 +3095,16 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI System.out.println("TRACE: compound_variable()"); } if (token == TokenNameVariable) { + if (!lefthandside) { + if (!containsVariableSet()) { +// reportSyntaxError("The local variable " + new String(scanner.getCurrentIdentifierSource()) +// + " may not have been initialized"); + problemReporter.uninitializedLocalVariable(new String(scanner.getCurrentIdentifierSource()),scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(), + referenceContext, compilationUnit.compilationResult); + } + } else { + addVariableSet(); + } FieldReference ref = new FieldReference(scanner.getCurrentIdentifierSource(), scanner.getCurrentTokenStartPosition()); getNextToken(); return ref; @@ -3105,7 +3141,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI System.out.println("TRACE: object_property()"); } if (token == TokenNameVariable || token == TokenNameDOLLAR) { - variable_without_objects(); + variable_without_objects(false); } else { object_dim_list(); } @@ -3171,23 +3207,23 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI } private void r_variable() { - variable(); + variable(false); } - private void w_variable() { - variable(); + private void w_variable(boolean lefthandside) { + variable(lefthandside); } private void rw_variable() { - variable(); + variable(false); } - private Expression variable() { + private Expression variable(boolean lefthandside) { // variable: // base_variable_with_function_calls T_OBJECT_OPERATOR // object_property method_or_not variable_properties // | base_variable_with_function_calls - Expression ref = base_variable_with_function_calls(); + Expression ref = base_variable_with_function_calls(lefthandside); if (token == TokenNameMINUS_GREATER) { ref = null; getNextToken(); @@ -3526,7 +3562,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI throwSyntaxError("'(' expected after keyword 'empty'"); } getNextToken(); - variable(); + variable(false); if (token != TokenNameRPAREN) { throwSyntaxError("')' expected after keyword 'empty'"); } @@ -3658,7 +3694,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI throwSyntaxError("Variable expected after keyword 'isset'"); } while (true) { - variable(); + variable(false); if (token == TokenNameCOMMA) { getNextToken(); } else { @@ -3976,6 +4012,8 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI HashMap fMethodVariables = null; + Stack fStackUnassigned = new Stack(); + //ast stack final static int AstStackIncrement = 100; @@ -4343,8 +4381,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI } } if (scanner.recordLineSeparator) { - compilationUnit.compilationResult.lineSeparatorPositions = - scanner.getLineEnds(); + compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds(); } // check placement anomalies against other kinds of brackets for (int kind = 0; kind < BracketKinds; kind++) { @@ -4480,4 +4517,83 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI //endPosition is just before the ; } + + public final static String[] GLOBALS = { + "$this", + "$_COOKIE", + "$_ENV", + "$_FILES", + "$_GET", + "$GLOBALS", + "$_POST", + "$_REQUEST", + "$_SESSION", + "$_SERVER" + }; + /** + * + */ + private void pushVariableSet() { + HashSet set =new HashSet(); + for (int i = 0; i < GLOBALS.length; i++) { + set.add(GLOBALS[i]); + } + fStackUnassigned.push(set); + } + + /** + * Returns the set of assigned variables returns null if no Set is defined at the current scanner position + */ + private HashSet peekVariableSet() { + if (!fStackUnassigned.isEmpty()) { + return (HashSet) fStackUnassigned.peek(); + } + return null; + } + + /** + * add the current identifier source to the set of assigned variables + * + * @param set + */ + private void addVariableSet(HashSet set) { + if (set != null) { + set.add(new String(scanner.getCurrentTokenSource())); + } + } + + /** + * add the current identifier source to the set of assigned variables + * + */ + private void addVariableSet() { + HashSet set = peekVariableSet(); + if (set != null) { + set.add(new String(scanner.getCurrentTokenSource())); + } + } + + /** + * add the current identifier source to the set of assigned variables + * + */ + private void addVariableSet(char[] token) { + HashSet set = peekVariableSet(); + if (set != null) { + set.add(new String(token)); + } + } + + /** + * check if the current identifier source is in the set of assigned variables Returns true, if no set is defined for the + * current scanner position + * + */ + private boolean containsVariableSet() { + HashSet set = peekVariableSet(); + if (set != null) { + return set.contains(new String(scanner.getCurrentTokenSource())); + } + return true; + } } \ No newline at end of file