| 2934 | |
| 2935 | |
| 2936 | bool Script::IsSOLContExpr(LineBuffer &next_buf) |
| 2937 | { |
| 2938 | LPTSTR cp, hotkey_flag; |
| 2939 | |
| 2940 | switch(ctoupper(*next_buf)) // Above has ensured *next_buf != '\0' (toupper might have problems with '\0'). |
| 2941 | { |
| 2942 | case 'A': // AND, AS (future use) |
| 2943 | case 'O': // OR |
| 2944 | case 'I': // IS, IN, (unwanted) ISSET |
| 2945 | case 'C': // CONTAINS (future use) |
| 2946 | // See comments in the default section further below. |
| 2947 | cp = find_identifier_end<LPTSTR>(next_buf); |
| 2948 | // Although (x)and(y) is technically valid, it's quite unusual. The space or tab requirement is kept |
| 2949 | // as the simplest way to allow method definitions to use these as names (when called, the leading dot |
| 2950 | // ensures there is no ambiguity). Note that checking if we're inside a class definition is not |
| 2951 | // sufficient because multi-line expressions are valid there too (i.e. for var initializers). |
| 2952 | // This also rules out valid double-derefs such as and%suffix% := 1. |
| 2953 | if (IS_SPACE_OR_TAB(*cp) && ConvertWordOperator(next_buf, cp - next_buf)) |
| 2954 | { |
| 2955 | // ISSET doesn't need to be excluded here because it can't be legally followed by a space or tab. |
| 2956 | // Unlike in v1, there's no check for an operator after AND/OR (such as AND := 1) because they |
| 2957 | // should never be used as variable names. |
| 2958 | return true; |
| 2959 | } |
| 2960 | break; |
| 2961 | default: |
| 2962 | // Desired line continuation operators: |
| 2963 | // Pretty much everything, namely: |
| 2964 | // +, -, *, /, //, **, <<, >>, &, |, ^, <, >, <=, >=, =, ==, <>, !=, :=, +=, -=, /=, *=, ?, : |
| 2965 | // And also the following remaining unaries (i.e. those that aren't also binaries): !, ~ |
| 2966 | // The first line below checks for ::, ++, and --. Those can't be continuation lines because: |
| 2967 | // "::" isn't a valid operator (this also helps performance if there are many hotstrings). |
| 2968 | // ++ and -- are ambiguous with an isolated line containing ++Var or --Var (and besides, |
| 2969 | // wanting to use ++ to continue an expression seems extremely rare, though if there's ever |
| 2970 | // demand for it, might be able to look at what lies to the right of the operator's operand |
| 2971 | // -- though that would produce inconsistent continuation behavior since ++Var itself still |
| 2972 | // could never be a continuation line due to ambiguity). |
| 2973 | // |
| 2974 | // The logic here isn't smart enough to differentiate between a leading - that's meant as a |
| 2975 | // continuation character and one that isn't. Even if it were, it would still be ambiguous in |
| 2976 | // some cases because the author's intent isn't known; for example, the leading minus sign on |
| 2977 | // the second line below is ambiguous: |
| 2978 | // x := y |
| 2979 | // -z ? a:=1 : func() |
| 2980 | if ((*next_buf == ':' || *next_buf == '+' || *next_buf == '-') && next_buf[1] == *next_buf // See above. |
| 2981 | || !_tcschr(CONTINUATION_LINE_SYMBOLS, *next_buf)) // Line doesn't start with a continuation char. |
| 2982 | break; |
| 2983 | // Some of the above checks must be done before the next ones. |
| 2984 | if ( !(hotkey_flag = _tcsstr(next_buf, HOTKEY_FLAG)) ) // Without any "::", it can't be a hotkey or hotstring. |
| 2985 | return true; |
| 2986 | if (*next_buf == ':') // First char is ':', so it's more likely a hotstring than a hotkey. |
| 2987 | { |
| 2988 | // Remember that hotstrings can contain what *appear* to be quoted literal strings, |
| 2989 | // so detecting whether a "::" is in a quoted/literal string in this case would |
| 2990 | // be more complicated. That's one reason this other method is used. |
| 2991 | bool hotstring_options_all_valid = true; |
| 2992 | for (cp = next_buf + 1; *cp && *cp != ':'; ++cp) |
| 2993 | if (!IS_HOTSTRING_OPTION(*cp)) // Not a perfect test, but eliminates most of what little remaining ambiguity exists between ':' as a continuation character vs. ':' as the start of a hotstring. It especially eliminates the ":=" operator. |
nothing calls this directly
no test coverage detected