[ruby/prism] Expose types on diagnostics

https://github.com/ruby/prism/commit/a735c2262f
This commit is contained in:
Kevin Newton 2024-03-06 13:18:55 -05:00
parent c0cb3f60e1
commit 38c2774420
9 changed files with 482 additions and 365 deletions

View File

@ -366,6 +366,9 @@ module Prism
# This represents an error that was encountered during parsing.
class ParseError
# The type of error.
attr_reader :type
# The message associated with this error.
attr_reader :message
@ -376,7 +379,8 @@ module Prism
attr_reader :level
# Create a new error object with the given message and location.
def initialize(message, location, level)
def initialize(type, message, location, level)
@type = type
@message = message
@location = location
@level = level
@ -384,17 +388,20 @@ module Prism
# Implement the hash pattern matching interface for ParseError.
def deconstruct_keys(keys)
{ message: message, location: location, level: level }
{ type: type, message: message, location: location, level: level }
end
# Returns a string representation of this error.
def inspect
"#<Prism::ParseError @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
"#<Prism::ParseError @type=#{@type.inspect} @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
end
end
# This represents a warning that was encountered during parsing.
class ParseWarning
# The type of warning.
attr_reader :type
# The message associated with this warning.
attr_reader :message
@ -405,7 +412,8 @@ module Prism
attr_reader :level
# Create a new warning object with the given message and location.
def initialize(message, location, level)
def initialize(type, message, location, level)
@type = type
@message = message
@location = location
@level = level
@ -413,12 +421,12 @@ module Prism
# Implement the hash pattern matching interface for ParseWarning.
def deconstruct_keys(keys)
{ message: message, location: location, level: level }
{ type: type, message: message, location: location, level: level }
end
# Returns a string representation of this warning.
def inspect
"#<Prism::ParseWarning @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
"#<Prism::ParseWarning @type=#{@type.inspect} @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
end
end

View File

@ -1,3 +1,241 @@
errors:
- CANNOT_PARSE_EXPRESSION
- ALIAS_ARGUMENT
- AMPAMPEQ_MULTI_ASSIGN
- ARGUMENT_AFTER_BLOCK
- ARGUMENT_AFTER_FORWARDING_ELLIPSES
- ARGUMENT_BARE_HASH
- ARGUMENT_BLOCK_FORWARDING
- ARGUMENT_BLOCK_MULTI
- ARGUMENT_FORMAL_CLASS
- ARGUMENT_FORMAL_CONSTANT
- ARGUMENT_FORMAL_GLOBAL
- ARGUMENT_FORMAL_IVAR
- ARGUMENT_FORWARDING_UNBOUND
- ARGUMENT_IN
- ARGUMENT_NO_FORWARDING_AMP
- ARGUMENT_NO_FORWARDING_ELLIPSES
- ARGUMENT_NO_FORWARDING_STAR
- ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT
- ARGUMENT_SPLAT_AFTER_SPLAT
- ARGUMENT_TERM_PAREN
- ARGUMENT_UNEXPECTED_BLOCK
- ARRAY_ELEMENT
- ARRAY_EXPRESSION
- ARRAY_EXPRESSION_AFTER_STAR
- ARRAY_SEPARATOR
- ARRAY_TERM
- BEGIN_LONELY_ELSE
- BEGIN_TERM
- BEGIN_UPCASE_BRACE
- BEGIN_UPCASE_TERM
- BEGIN_UPCASE_TOPLEVEL
- BLOCK_PARAM_LOCAL_VARIABLE
- BLOCK_PARAM_PIPE_TERM
- BLOCK_TERM_BRACE
- BLOCK_TERM_END
- CANNOT_PARSE_STRING_PART
- CASE_EXPRESSION_AFTER_CASE
- CASE_EXPRESSION_AFTER_WHEN
- CASE_MATCH_MISSING_PREDICATE
- CASE_MISSING_CONDITIONS
- CASE_TERM
- CLASS_IN_METHOD
- CLASS_NAME
- CLASS_SUPERCLASS
- CLASS_TERM
- CLASS_UNEXPECTED_END
- CONDITIONAL_ELSIF_PREDICATE
- CONDITIONAL_IF_PREDICATE
- CONDITIONAL_PREDICATE_TERM
- CONDITIONAL_TERM
- CONDITIONAL_TERM_ELSE
- CONDITIONAL_UNLESS_PREDICATE
- CONDITIONAL_UNTIL_PREDICATE
- CONDITIONAL_WHILE_PREDICATE
- CONSTANT_PATH_COLON_COLON_CONSTANT
- DEF_ENDLESS
- DEF_ENDLESS_SETTER
- DEF_NAME
- DEF_NAME_AFTER_RECEIVER
- DEF_PARAMS_TERM
- DEF_PARAMS_TERM_PAREN
- DEF_RECEIVER
- DEF_RECEIVER_TERM
- DEF_TERM
- DEFINED_EXPRESSION
- EMBDOC_TERM
- EMBEXPR_END
- EMBVAR_INVALID
- END_UPCASE_BRACE
- END_UPCASE_TERM
- ESCAPE_INVALID_CONTROL
- ESCAPE_INVALID_CONTROL_REPEAT
- ESCAPE_INVALID_HEXADECIMAL
- ESCAPE_INVALID_META
- ESCAPE_INVALID_META_REPEAT
- ESCAPE_INVALID_UNICODE
- ESCAPE_INVALID_UNICODE_CM_FLAGS
- ESCAPE_INVALID_UNICODE_LITERAL
- ESCAPE_INVALID_UNICODE_LONG
- ESCAPE_INVALID_UNICODE_TERM
- EXPECT_ARGUMENT
- EXPECT_EOL_AFTER_STATEMENT
- EXPECT_EXPRESSION_AFTER_AMPAMPEQ
- EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ
- EXPECT_EXPRESSION_AFTER_COMMA
- EXPECT_EXPRESSION_AFTER_EQUAL
- EXPECT_EXPRESSION_AFTER_LESS_LESS
- EXPECT_EXPRESSION_AFTER_LPAREN
- EXPECT_EXPRESSION_AFTER_QUESTION
- EXPECT_EXPRESSION_AFTER_OPERATOR
- EXPECT_EXPRESSION_AFTER_SPLAT
- EXPECT_EXPRESSION_AFTER_SPLAT_HASH
- EXPECT_EXPRESSION_AFTER_STAR
- EXPECT_IDENT_REQ_PARAMETER
- EXPECT_LPAREN_REQ_PARAMETER
- EXPECT_RBRACKET
- EXPECT_RPAREN
- EXPECT_RPAREN_AFTER_MULTI
- EXPECT_RPAREN_REQ_PARAMETER
- EXPECT_STRING_CONTENT
- EXPECT_WHEN_DELIMITER
- EXPRESSION_BARE_HASH
- FLOAT_PARSE
- FOR_COLLECTION
- FOR_IN
- FOR_INDEX
- FOR_TERM
- HASH_EXPRESSION_AFTER_LABEL
- HASH_KEY
- HASH_ROCKET
- HASH_TERM
- HASH_VALUE
- HEREDOC_TERM
- INCOMPLETE_QUESTION_MARK
- INCOMPLETE_VARIABLE_CLASS_3_3_0
- INCOMPLETE_VARIABLE_CLASS
- INCOMPLETE_VARIABLE_INSTANCE_3_3_0
- INCOMPLETE_VARIABLE_INSTANCE
- INVALID_ENCODING_MAGIC_COMMENT
- INVALID_FLOAT_EXPONENT
- INVALID_NUMBER_BINARY
- INVALID_NUMBER_DECIMAL
- INVALID_NUMBER_HEXADECIMAL
- INVALID_NUMBER_OCTAL
- INVALID_NUMBER_UNDERSCORE
- INVALID_CHARACTER
- INVALID_MULTIBYTE_CHARACTER
- INVALID_PRINTABLE_CHARACTER
- INVALID_PERCENT
- INVALID_VARIABLE_GLOBAL_3_3_0
- INVALID_VARIABLE_GLOBAL
- IT_NOT_ALLOWED_NUMBERED
- IT_NOT_ALLOWED_ORDINARY
- LAMBDA_OPEN
- LAMBDA_TERM_BRACE
- LAMBDA_TERM_END
- LIST_I_LOWER_ELEMENT
- LIST_I_LOWER_TERM
- LIST_I_UPPER_ELEMENT
- LIST_I_UPPER_TERM
- LIST_W_LOWER_ELEMENT
- LIST_W_LOWER_TERM
- LIST_W_UPPER_ELEMENT
- LIST_W_UPPER_TERM
- MALLOC_FAILED
- MIXED_ENCODING
- MODULE_IN_METHOD
- MODULE_NAME
- MODULE_TERM
- MULTI_ASSIGN_MULTI_SPLATS
- MULTI_ASSIGN_UNEXPECTED_REST
- NOT_EXPRESSION
- NO_LOCAL_VARIABLE
- NUMBER_LITERAL_UNDERSCORE
- NUMBERED_PARAMETER_IT
- NUMBERED_PARAMETER_ORDINARY
- NUMBERED_PARAMETER_OUTER_SCOPE
- OPERATOR_MULTI_ASSIGN
- OPERATOR_WRITE_ARGUMENTS
- OPERATOR_WRITE_BLOCK
- PARAMETER_ASSOC_SPLAT_MULTI
- PARAMETER_BLOCK_MULTI
- PARAMETER_CIRCULAR
- PARAMETER_METHOD_NAME
- PARAMETER_NAME_REPEAT
- PARAMETER_NO_DEFAULT
- PARAMETER_NO_DEFAULT_KW
- PARAMETER_NUMBERED_RESERVED
- PARAMETER_ORDER
- PARAMETER_SPLAT_MULTI
- PARAMETER_STAR
- PARAMETER_UNEXPECTED_FWD
- PARAMETER_WILD_LOOSE_COMMA
- PATTERN_EXPRESSION_AFTER_BRACKET
- PATTERN_EXPRESSION_AFTER_HROCKET
- PATTERN_EXPRESSION_AFTER_COMMA
- PATTERN_EXPRESSION_AFTER_IN
- PATTERN_EXPRESSION_AFTER_KEY
- PATTERN_EXPRESSION_AFTER_PAREN
- PATTERN_EXPRESSION_AFTER_PIN
- PATTERN_EXPRESSION_AFTER_PIPE
- PATTERN_EXPRESSION_AFTER_RANGE
- PATTERN_EXPRESSION_AFTER_REST
- PATTERN_HASH_KEY
- PATTERN_HASH_KEY_LABEL
- PATTERN_IDENT_AFTER_HROCKET
- PATTERN_LABEL_AFTER_COMMA
- PATTERN_REST
- PATTERN_TERM_BRACE
- PATTERN_TERM_BRACKET
- PATTERN_TERM_PAREN
- PIPEPIPEEQ_MULTI_ASSIGN
- REGEXP_TERM
- RESCUE_EXPRESSION
- RESCUE_MODIFIER_VALUE
- RESCUE_TERM
- RESCUE_VARIABLE
- RETURN_INVALID
- SINGLETON_FOR_LITERALS
- STATEMENT_ALIAS
- STATEMENT_POSTEXE_END
- STATEMENT_PREEXE_BEGIN
- STATEMENT_UNDEF
- STRING_CONCATENATION
- STRING_INTERPOLATED_TERM
- STRING_LITERAL_EOF
- STRING_LITERAL_TERM
- SYMBOL_INVALID
- SYMBOL_TERM_DYNAMIC
- SYMBOL_TERM_INTERPOLATED
- TERNARY_COLON
- TERNARY_EXPRESSION_FALSE
- TERNARY_EXPRESSION_TRUE
- UNARY_RECEIVER
- UNEXPECTED_TOKEN_CLOSE_CONTEXT
- UNEXPECTED_TOKEN_IGNORE
- UNDEF_ARGUMENT
- UNTIL_TERM
- VOID_EXPRESSION
- WHILE_TERM
- WRITE_TARGET_IN_METHOD
- WRITE_TARGET_READONLY
- WRITE_TARGET_UNEXPECTED
- XSTRING_TERM
warnings:
- AMBIGUOUS_FIRST_ARGUMENT_MINUS
- AMBIGUOUS_FIRST_ARGUMENT_PLUS
- AMBIGUOUS_PREFIX_STAR
- AMBIGUOUS_SLASH
- DOT_DOT_DOT_EOL
- EQUAL_IN_CONDITIONAL
- END_IN_METHOD
- DUPLICATED_HASH_KEY
- DUPLICATED_WHEN_CLAUSE
- FLOAT_OUT_OF_RANGE
- INTEGER_IN_FLIP_FLOP
- KEYWORD_EOL
tokens:
- name: EOF
value: 1

View File

@ -1,352 +0,0 @@
/**
* @file diagnostic.h
*
* A list of diagnostics generated during parsing.
*/
#ifndef PRISM_DIAGNOSTIC_H
#define PRISM_DIAGNOSTIC_H
#include "prism/ast.h"
#include "prism/defines.h"
#include "prism/util/pm_list.h"
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
/**
* The levels of errors generated during parsing.
*/
typedef enum {
/** For errors that cannot be recovered from. */
PM_ERROR_LEVEL_FATAL = 0,
/** For errors that should raise an argument error. */
PM_ERROR_LEVEL_ARGUMENT = 1
} pm_error_level_t;
/**
* The levels of warnings generated during parsing.
*/
typedef enum {
/** For warnings which should be emitted if $VERBOSE != nil. */
PM_WARNING_LEVEL_DEFAULT = 0,
/** For warnings which should be emitted if $VERBOSE == true. */
PM_WARNING_LEVEL_VERBOSE = 1
} pm_warning_level_t;
/**
* This struct represents a diagnostic generated during parsing.
*
* @extends pm_list_node_t
*/
typedef struct {
/** The embedded base node. */
pm_list_node_t node;
/** The location of the diagnostic in the source. */
pm_location_t location;
/** The message associated with the diagnostic. */
const char *message;
/**
* Whether or not the memory related to the message of this diagnostic is
* owned by this diagnostic. If it is, it needs to be freed when the
* diagnostic is freed.
*/
bool owned;
/**
* The level of the diagnostic, see `pm_error_level_t` and
* `pm_warning_level_t` for possible values.
*/
uint8_t level;
} pm_diagnostic_t;
/**
* The diagnostic IDs of all of the diagnostics, used to communicate the types
* of errors between the parser and the user.
*/
typedef enum {
// This is a special error that we can potentially replace by others. For
// an example of how this is used, see parse_expression_prefix.
PM_ERR_CANNOT_PARSE_EXPRESSION,
// These are the error codes.
PM_ERR_ALIAS_ARGUMENT,
PM_ERR_AMPAMPEQ_MULTI_ASSIGN,
PM_ERR_ARGUMENT_AFTER_BLOCK,
PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES,
PM_ERR_ARGUMENT_BARE_HASH,
PM_ERR_ARGUMENT_BLOCK_FORWARDING,
PM_ERR_ARGUMENT_BLOCK_MULTI,
PM_ERR_ARGUMENT_FORMAL_CLASS,
PM_ERR_ARGUMENT_FORMAL_CONSTANT,
PM_ERR_ARGUMENT_FORMAL_GLOBAL,
PM_ERR_ARGUMENT_FORMAL_IVAR,
PM_ERR_ARGUMENT_FORWARDING_UNBOUND,
PM_ERR_ARGUMENT_IN,
PM_ERR_ARGUMENT_NO_FORWARDING_AMP,
PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES,
PM_ERR_ARGUMENT_NO_FORWARDING_STAR,
PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT,
PM_ERR_ARGUMENT_SPLAT_AFTER_SPLAT,
PM_ERR_ARGUMENT_TERM_PAREN,
PM_ERR_ARGUMENT_UNEXPECTED_BLOCK,
PM_ERR_ARRAY_ELEMENT,
PM_ERR_ARRAY_EXPRESSION,
PM_ERR_ARRAY_EXPRESSION_AFTER_STAR,
PM_ERR_ARRAY_SEPARATOR,
PM_ERR_ARRAY_TERM,
PM_ERR_BEGIN_LONELY_ELSE,
PM_ERR_BEGIN_TERM,
PM_ERR_BEGIN_UPCASE_BRACE,
PM_ERR_BEGIN_UPCASE_TERM,
PM_ERR_BEGIN_UPCASE_TOPLEVEL,
PM_ERR_BLOCK_PARAM_LOCAL_VARIABLE,
PM_ERR_BLOCK_PARAM_PIPE_TERM,
PM_ERR_BLOCK_TERM_BRACE,
PM_ERR_BLOCK_TERM_END,
PM_ERR_CANNOT_PARSE_STRING_PART,
PM_ERR_CASE_EXPRESSION_AFTER_CASE,
PM_ERR_CASE_EXPRESSION_AFTER_WHEN,
PM_ERR_CASE_MATCH_MISSING_PREDICATE,
PM_ERR_CASE_MISSING_CONDITIONS,
PM_ERR_CASE_TERM,
PM_ERR_CLASS_IN_METHOD,
PM_ERR_CLASS_NAME,
PM_ERR_CLASS_SUPERCLASS,
PM_ERR_CLASS_TERM,
PM_ERR_CLASS_UNEXPECTED_END,
PM_ERR_CONDITIONAL_ELSIF_PREDICATE,
PM_ERR_CONDITIONAL_IF_PREDICATE,
PM_ERR_CONDITIONAL_PREDICATE_TERM,
PM_ERR_CONDITIONAL_TERM,
PM_ERR_CONDITIONAL_TERM_ELSE,
PM_ERR_CONDITIONAL_UNLESS_PREDICATE,
PM_ERR_CONDITIONAL_UNTIL_PREDICATE,
PM_ERR_CONDITIONAL_WHILE_PREDICATE,
PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT,
PM_ERR_DEF_ENDLESS,
PM_ERR_DEF_ENDLESS_SETTER,
PM_ERR_DEF_NAME,
PM_ERR_DEF_NAME_AFTER_RECEIVER,
PM_ERR_DEF_PARAMS_TERM,
PM_ERR_DEF_PARAMS_TERM_PAREN,
PM_ERR_DEF_RECEIVER,
PM_ERR_DEF_RECEIVER_TERM,
PM_ERR_DEF_TERM,
PM_ERR_DEFINED_EXPRESSION,
PM_ERR_EMBDOC_TERM,
PM_ERR_EMBEXPR_END,
PM_ERR_EMBVAR_INVALID,
PM_ERR_END_UPCASE_BRACE,
PM_ERR_END_UPCASE_TERM,
PM_ERR_ESCAPE_INVALID_CONTROL,
PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT,
PM_ERR_ESCAPE_INVALID_HEXADECIMAL,
PM_ERR_ESCAPE_INVALID_META,
PM_ERR_ESCAPE_INVALID_META_REPEAT,
PM_ERR_ESCAPE_INVALID_UNICODE,
PM_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS,
PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL,
PM_ERR_ESCAPE_INVALID_UNICODE_LONG,
PM_ERR_ESCAPE_INVALID_UNICODE_TERM,
PM_ERR_EXPECT_ARGUMENT,
PM_ERR_EXPECT_EOL_AFTER_STATEMENT,
PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ,
PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ,
PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA,
PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL,
PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS,
PM_ERR_EXPECT_EXPRESSION_AFTER_LPAREN,
PM_ERR_EXPECT_EXPRESSION_AFTER_QUESTION,
PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR,
PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT,
PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH,
PM_ERR_EXPECT_EXPRESSION_AFTER_STAR,
PM_ERR_EXPECT_IDENT_REQ_PARAMETER,
PM_ERR_EXPECT_LPAREN_REQ_PARAMETER,
PM_ERR_EXPECT_RBRACKET,
PM_ERR_EXPECT_RPAREN,
PM_ERR_EXPECT_RPAREN_AFTER_MULTI,
PM_ERR_EXPECT_RPAREN_REQ_PARAMETER,
PM_ERR_EXPECT_STRING_CONTENT,
PM_ERR_EXPECT_WHEN_DELIMITER,
PM_ERR_EXPRESSION_BARE_HASH,
PM_ERR_FLOAT_PARSE,
PM_ERR_FOR_COLLECTION,
PM_ERR_FOR_IN,
PM_ERR_FOR_INDEX,
PM_ERR_FOR_TERM,
PM_ERR_HASH_EXPRESSION_AFTER_LABEL,
PM_ERR_HASH_KEY,
PM_ERR_HASH_ROCKET,
PM_ERR_HASH_TERM,
PM_ERR_HASH_VALUE,
PM_ERR_HEREDOC_TERM,
PM_ERR_INCOMPLETE_QUESTION_MARK,
PM_ERR_INCOMPLETE_VARIABLE_CLASS_3_3_0,
PM_ERR_INCOMPLETE_VARIABLE_CLASS,
PM_ERR_INCOMPLETE_VARIABLE_INSTANCE_3_3_0,
PM_ERR_INCOMPLETE_VARIABLE_INSTANCE,
PM_ERR_INVALID_ENCODING_MAGIC_COMMENT,
PM_ERR_INVALID_FLOAT_EXPONENT,
PM_ERR_INVALID_NUMBER_BINARY,
PM_ERR_INVALID_NUMBER_DECIMAL,
PM_ERR_INVALID_NUMBER_HEXADECIMAL,
PM_ERR_INVALID_NUMBER_OCTAL,
PM_ERR_INVALID_NUMBER_UNDERSCORE,
PM_ERR_INVALID_CHARACTER,
PM_ERR_INVALID_MULTIBYTE_CHARACTER,
PM_ERR_INVALID_PRINTABLE_CHARACTER,
PM_ERR_INVALID_PERCENT,
PM_ERR_INVALID_VARIABLE_GLOBAL_3_3_0,
PM_ERR_INVALID_VARIABLE_GLOBAL,
PM_ERR_IT_NOT_ALLOWED_NUMBERED,
PM_ERR_IT_NOT_ALLOWED_ORDINARY,
PM_ERR_LAMBDA_OPEN,
PM_ERR_LAMBDA_TERM_BRACE,
PM_ERR_LAMBDA_TERM_END,
PM_ERR_LIST_I_LOWER_ELEMENT,
PM_ERR_LIST_I_LOWER_TERM,
PM_ERR_LIST_I_UPPER_ELEMENT,
PM_ERR_LIST_I_UPPER_TERM,
PM_ERR_LIST_W_LOWER_ELEMENT,
PM_ERR_LIST_W_LOWER_TERM,
PM_ERR_LIST_W_UPPER_ELEMENT,
PM_ERR_LIST_W_UPPER_TERM,
PM_ERR_MALLOC_FAILED,
PM_ERR_MIXED_ENCODING,
PM_ERR_MODULE_IN_METHOD,
PM_ERR_MODULE_NAME,
PM_ERR_MODULE_TERM,
PM_ERR_MULTI_ASSIGN_MULTI_SPLATS,
PM_ERR_MULTI_ASSIGN_UNEXPECTED_REST,
PM_ERR_NOT_EXPRESSION,
PM_ERR_NO_LOCAL_VARIABLE,
PM_ERR_NUMBER_LITERAL_UNDERSCORE,
PM_ERR_NUMBERED_PARAMETER_IT,
PM_ERR_NUMBERED_PARAMETER_ORDINARY,
PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE,
PM_ERR_OPERATOR_MULTI_ASSIGN,
PM_ERR_OPERATOR_WRITE_ARGUMENTS,
PM_ERR_OPERATOR_WRITE_BLOCK,
PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI,
PM_ERR_PARAMETER_BLOCK_MULTI,
PM_ERR_PARAMETER_CIRCULAR,
PM_ERR_PARAMETER_METHOD_NAME,
PM_ERR_PARAMETER_NAME_REPEAT,
PM_ERR_PARAMETER_NO_DEFAULT,
PM_ERR_PARAMETER_NO_DEFAULT_KW,
PM_ERR_PARAMETER_NUMBERED_RESERVED,
PM_ERR_PARAMETER_ORDER,
PM_ERR_PARAMETER_SPLAT_MULTI,
PM_ERR_PARAMETER_STAR,
PM_ERR_PARAMETER_UNEXPECTED_FWD,
PM_ERR_PARAMETER_WILD_LOOSE_COMMA,
PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET,
PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET,
PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA,
PM_ERR_PATTERN_EXPRESSION_AFTER_IN,
PM_ERR_PATTERN_EXPRESSION_AFTER_KEY,
PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN,
PM_ERR_PATTERN_EXPRESSION_AFTER_PIN,
PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE,
PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE,
PM_ERR_PATTERN_EXPRESSION_AFTER_REST,
PM_ERR_PATTERN_HASH_KEY,
PM_ERR_PATTERN_HASH_KEY_LABEL,
PM_ERR_PATTERN_IDENT_AFTER_HROCKET,
PM_ERR_PATTERN_LABEL_AFTER_COMMA,
PM_ERR_PATTERN_REST,
PM_ERR_PATTERN_TERM_BRACE,
PM_ERR_PATTERN_TERM_BRACKET,
PM_ERR_PATTERN_TERM_PAREN,
PM_ERR_PIPEPIPEEQ_MULTI_ASSIGN,
PM_ERR_REGEXP_TERM,
PM_ERR_RESCUE_EXPRESSION,
PM_ERR_RESCUE_MODIFIER_VALUE,
PM_ERR_RESCUE_TERM,
PM_ERR_RESCUE_VARIABLE,
PM_ERR_RETURN_INVALID,
PM_ERR_SINGLETON_FOR_LITERALS,
PM_ERR_STATEMENT_ALIAS,
PM_ERR_STATEMENT_POSTEXE_END,
PM_ERR_STATEMENT_PREEXE_BEGIN,
PM_ERR_STATEMENT_UNDEF,
PM_ERR_STRING_CONCATENATION,
PM_ERR_STRING_INTERPOLATED_TERM,
PM_ERR_STRING_LITERAL_EOF,
PM_ERR_STRING_LITERAL_TERM,
PM_ERR_SYMBOL_INVALID,
PM_ERR_SYMBOL_TERM_DYNAMIC,
PM_ERR_SYMBOL_TERM_INTERPOLATED,
PM_ERR_TERNARY_COLON,
PM_ERR_TERNARY_EXPRESSION_FALSE,
PM_ERR_TERNARY_EXPRESSION_TRUE,
PM_ERR_UNARY_RECEIVER,
PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT,
PM_ERR_UNEXPECTED_TOKEN_IGNORE,
PM_ERR_UNDEF_ARGUMENT,
PM_ERR_UNTIL_TERM,
PM_ERR_VOID_EXPRESSION,
PM_ERR_WHILE_TERM,
PM_ERR_WRITE_TARGET_IN_METHOD,
PM_ERR_WRITE_TARGET_READONLY,
PM_ERR_WRITE_TARGET_UNEXPECTED,
PM_ERR_XSTRING_TERM,
// These are the warning codes.
PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS,
PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS,
PM_WARN_AMBIGUOUS_PREFIX_STAR,
PM_WARN_AMBIGUOUS_SLASH,
PM_WARN_DOT_DOT_DOT_EOL,
PM_WARN_EQUAL_IN_CONDITIONAL,
PM_WARN_END_IN_METHOD,
PM_WARN_DUPLICATED_HASH_KEY,
PM_WARN_DUPLICATED_WHEN_CLAUSE,
PM_WARN_FLOAT_OUT_OF_RANGE,
PM_WARN_INTEGER_IN_FLIP_FLOP,
PM_WARN_KEYWORD_EOL,
// This is the number of diagnostic codes.
PM_DIAGNOSTIC_ID_LEN,
} pm_diagnostic_id_t;
/**
* Append a diagnostic to the given list of diagnostics that is using shared
* memory for its message.
*
* @param list The list to append to.
* @param start The start of the diagnostic.
* @param end The end of the diagnostic.
* @param diag_id The diagnostic ID.
* @return Whether the diagnostic was successfully appended.
*/
bool pm_diagnostic_list_append(pm_list_t *list, const uint8_t *start, const uint8_t *end, pm_diagnostic_id_t diag_id);
/**
* Append a diagnostic to the given list of diagnostics that is using a format
* string for its message.
*
* @param list The list to append to.
* @param start The start of the diagnostic.
* @param end The end of the diagnostic.
* @param diag_id The diagnostic ID.
* @param ... The arguments to the format string for the message.
* @return Whether the diagnostic was successfully appended.
*/
bool pm_diagnostic_list_append_format(pm_list_t *list, const uint8_t *start, const uint8_t *end, pm_diagnostic_id_t diag_id, ...);
/**
* Deallocate the internal state of the given diagnostic list.
*
* @param list The list to deallocate.
*/
void pm_diagnostic_list_free(pm_list_t *list);
#endif

View File

@ -452,12 +452,13 @@ parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
}
VALUE error_argv[] = {
ID2SYM(rb_intern(pm_diagnostic_id_human(error->diag_id))),
rb_enc_str_new_cstr(error->message, encoding),
rb_class_new_instance(3, location_argv, rb_cPrismLocation),
level
};
rb_ary_push(errors, rb_class_new_instance(3, error_argv, rb_cPrismParseError));
rb_ary_push(errors, rb_class_new_instance(4, error_argv, rb_cPrismParseError));
}
return errors;
@ -491,12 +492,13 @@ parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
}
VALUE warning_argv[] = {
ID2SYM(rb_intern(pm_diagnostic_id_human(warning->diag_id))),
rb_enc_str_new_cstr(warning->message, encoding),
rb_class_new_instance(3, location_argv, rb_cPrismLocation),
level
};
rb_ary_push(warnings, rb_class_new_instance(3, warning_argv, rb_cPrismParseWarning));
rb_ary_push(warnings, rb_class_new_instance(4, warning_argv, rb_cPrismParseWarning));
}
return warnings;

View File

@ -0,0 +1,127 @@
/**
* @file diagnostic.h
*
* A list of diagnostics generated during parsing.
*/
#ifndef PRISM_DIAGNOSTIC_H
#define PRISM_DIAGNOSTIC_H
#include "prism/ast.h"
#include "prism/defines.h"
#include "prism/util/pm_list.h"
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
/**
* The diagnostic IDs of all of the diagnostics, used to communicate the types
* of errors between the parser and the user.
*/
typedef enum {
// These are the error diagnostics.
<%- errors.each do |error| -%>
PM_ERR_<%= error.name %>,
<%- end -%>
// These are the warning diagnostics.
<%- warnings.each do |warning| -%>
PM_WARN_<%= warning.name %>,
<%- end -%>
} pm_diagnostic_id_t;
/**
* This struct represents a diagnostic generated during parsing.
*
* @extends pm_list_node_t
*/
typedef struct {
/** The embedded base node. */
pm_list_node_t node;
/** The location of the diagnostic in the source. */
pm_location_t location;
/** The ID of the diagnostic. */
pm_diagnostic_id_t diag_id;
/** The message associated with the diagnostic. */
const char *message;
/**
* Whether or not the memory related to the message of this diagnostic is
* owned by this diagnostic. If it is, it needs to be freed when the
* diagnostic is freed.
*/
bool owned;
/**
* The level of the diagnostic, see `pm_error_level_t` and
* `pm_warning_level_t` for possible values.
*/
uint8_t level;
} pm_diagnostic_t;
/**
* The levels of errors generated during parsing.
*/
typedef enum {
/** For errors that cannot be recovered from. */
PM_ERROR_LEVEL_FATAL = 0,
/** For errors that should raise an argument error. */
PM_ERROR_LEVEL_ARGUMENT = 1
} pm_error_level_t;
/**
* The levels of warnings generated during parsing.
*/
typedef enum {
/** For warnings which should be emitted if $VERBOSE != nil. */
PM_WARNING_LEVEL_DEFAULT = 0,
/** For warnings which should be emitted if $VERBOSE == true. */
PM_WARNING_LEVEL_VERBOSE = 1
} pm_warning_level_t;
/**
* Get the human-readable name of the given diagnostic ID.
*
* @param diag_id The diagnostic ID.
* @return The human-readable name of the diagnostic ID.
*/
const char * pm_diagnostic_id_human(pm_diagnostic_id_t diag_id);
/**
* Append a diagnostic to the given list of diagnostics that is using shared
* memory for its message.
*
* @param list The list to append to.
* @param start The start of the diagnostic.
* @param end The end of the diagnostic.
* @param diag_id The diagnostic ID.
* @return Whether the diagnostic was successfully appended.
*/
bool pm_diagnostic_list_append(pm_list_t *list, const uint8_t *start, const uint8_t *end, pm_diagnostic_id_t diag_id);
/**
* Append a diagnostic to the given list of diagnostics that is using a format
* string for its message.
*
* @param list The list to append to.
* @param start The start of the diagnostic.
* @param end The end of the diagnostic.
* @param diag_id The diagnostic ID.
* @param ... The arguments to the format string for the message.
* @return Whether the diagnostic was successfully appended.
*/
bool pm_diagnostic_list_append_format(pm_list_t *list, const uint8_t *start, const uint8_t *end, pm_diagnostic_id_t diag_id, ...);
/**
* Deallocate the internal state of the given diagnostic list.
*
* @param list The list to deallocate.
*/
void pm_diagnostic_list_free(pm_list_t *list);
#endif

View File

@ -116,12 +116,23 @@ module Prism
end
end
DIAGNOSTIC_TYPES = [
<%- errors.each do |error| -%>
<%= error.name.downcase.to_sym.inspect %>,
<%- end -%>
<%- warnings.each do |warning| -%>
<%= warning.name.downcase.to_sym.inspect %>,
<%- end -%>
].freeze
private_constant :DIAGNOSTIC_TYPES
def load_metadata
comments = load_comments
magic_comments = Array.new(load_varuint) { MagicComment.new(load_location_object, load_location_object) }
data_loc = load_optional_location_object
errors = Array.new(load_varuint) { ParseError.new(load_embedded_string, load_location_object, load_error_level) }
warnings = Array.new(load_varuint) { ParseWarning.new(load_embedded_string, load_location_object, load_warning_level) }
errors = Array.new(load_varuint) { ParseError.new(DIAGNOSTIC_TYPES[io.getbyte], load_embedded_string, load_location_object, load_error_level) }
warnings = Array.new(load_varuint) { ParseWarning.new(DIAGNOSTIC_TYPES[io.getbyte], load_embedded_string, load_location_object, load_warning_level) }
[comments, magic_comments, data_loc, errors, warnings]
end

View File

@ -1,5 +1,7 @@
#include "prism/diagnostic.h"
#define PM_DIAGNOSTIC_ID_MAX <%= errors.length + warnings.length %>
/** This struct holds the data for each diagnostic. */
typedef struct {
/** The message associated with the diagnostic. */
@ -71,7 +73,7 @@ typedef struct {
* * `PM_WARNING_LEVEL_DEFAULT` - Warnings that appear for `ruby -c -e 'code'`.
* * `PM_WARNING_LEVEL_VERBOSE` - Warnings that appear with `-w`, as in `ruby -w -c -e 'code'`.
*/
static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
// Special error that can be replaced
[PM_ERR_CANNOT_PARSE_EXPRESSION] = { "cannot parse the expression", PM_ERROR_LEVEL_FATAL },
@ -316,9 +318,24 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
[PM_WARN_KEYWORD_EOL] = { "`%.*s` at the end of line without an expression", PM_WARNING_LEVEL_VERBOSE }
};
/**
* Get the human-readable name of the given diagnostic ID.
*/
const char *
pm_diagnostic_id_human(pm_diagnostic_id_t diag_id) {
switch (diag_id) {
<%- errors.each do |error| -%>
case PM_ERR_<%= error.name %>: return "<%= error.name.downcase %>";
<%- end -%>
<%- warnings.each do |warning| -%>
case PM_WARN_<%= warning.name %>: return "<%= warning.name.downcase %>";
<%- end -%>
}
}
static inline const char *
pm_diagnostic_message(pm_diagnostic_id_t diag_id) {
assert(diag_id < PM_DIAGNOSTIC_ID_LEN);
assert(diag_id < PM_DIAGNOSTIC_ID_MAX);
const char *message = diagnostic_messages[diag_id].message;
assert(message);
@ -328,7 +345,7 @@ pm_diagnostic_message(pm_diagnostic_id_t diag_id) {
static inline uint8_t
pm_diagnostic_level(pm_diagnostic_id_t diag_id) {
assert(diag_id < PM_DIAGNOSTIC_ID_LEN);
assert(diag_id < PM_DIAGNOSTIC_ID_MAX);
return (uint8_t) diagnostic_messages[diag_id].level;
}
@ -343,6 +360,7 @@ pm_diagnostic_list_append(pm_list_t *list, const uint8_t *start, const uint8_t *
*diagnostic = (pm_diagnostic_t) {
.location = { start, end },
.diag_id = diag_id,
.message = pm_diagnostic_message(diag_id),
.owned = false,
.level = pm_diagnostic_level(diag_id)
@ -387,6 +405,7 @@ pm_diagnostic_list_append_format(pm_list_t *list, const uint8_t *start, const ui
*diagnostic = (pm_diagnostic_t) {
.location = { start, end },
.diag_id = diag_id,
.message = message,
.owned = true,
.level = pm_diagnostic_level(diag_id)

View File

@ -210,6 +210,9 @@ pm_serialize_data_loc(const pm_parser_t *parser, pm_buffer_t *buffer) {
static void
pm_serialize_diagnostic(pm_parser_t *parser, pm_diagnostic_t *diagnostic, pm_buffer_t *buffer) {
// serialize the type
pm_buffer_append_byte(buffer, (uint8_t) diagnostic->diag_id);
// serialize message
size_t message_length = strlen(diagnostic->message);
pm_buffer_append_varuint(buffer, pm_sizet_to_u32(message_length));

View File

@ -13,6 +13,22 @@ module Prism
JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "truffleruby"
JAVA_STRING_TYPE = JAVA_BACKEND == "jruby" ? "org.jruby.RubySymbol" : "String"
class Error
attr_reader :name
def initialize(name)
@name = name
end
end
class Warning
attr_reader :name
def initialize(name)
@name = name
end
end
# This module contains methods for escaping characters in JavaDoc comments.
module JavaDoc
ESCAPES = {
@ -521,6 +537,7 @@ module Prism
if you are looking to modify the template
=end
<<<<<<< HEAD
HEADING
when ".rbs"
<<~HEADING
@ -551,8 +568,18 @@ module Prism
/******************************************************************************/
HEADING
=======
{
errors: config.fetch("errors").map { |name| Error.new(name) },
warnings: config.fetch("warnings").map { |name| Warning.new(name) },
nodes: config.fetch("nodes").map { |node| NodeType.new(node) }.sort_by(&:name),
tokens: config.fetch("tokens").map { |token| Token.new(token) },
flags: config.fetch("flags").map { |flags| Flags.new(flags) }
}
>>>>>>> 35d292f929 (Expose types on diagnostics)
end
<<<<<<< HEAD
write_to ||= File.expand_path("../#{name}", __dir__)
contents = heading + erb.result_with_hash(locals)
@ -627,6 +654,40 @@ module Prism
"sig/prism/_private/dot_visitor.rbs"
]
end
=======
TEMPLATES = [
"ext/prism/api_node.c",
"include/prism/ast.h",
"include/prism/diagnostic.h",
"javascript/src/deserialize.js",
"javascript/src/nodes.js",
"javascript/src/visitor.js",
"java/org/prism/Loader.java",
"java/org/prism/Nodes.java",
"java/org/prism/AbstractNodeVisitor.java",
"lib/prism/compiler.rb",
"lib/prism/dispatcher.rb",
"lib/prism/dot_visitor.rb",
"lib/prism/dsl.rb",
"lib/prism/mutation_compiler.rb",
"lib/prism/node.rb",
"lib/prism/serialize.rb",
"lib/prism/visitor.rb",
"src/diagnostic.c",
"src/node.c",
"src/prettyprint.c",
"src/serialize.c",
"src/token_type.c",
"rbi/prism/node.rbi",
"rbi/prism/visitor.rbi",
"sig/prism.rbs",
"sig/prism/dsl.rbs",
"sig/prism/mutation_compiler.rbs",
"sig/prism/node.rbs",
"sig/prism/visitor.rbs",
"sig/prism/_private/dot_visitor.rbs"
]
>>>>>>> 35d292f929 (Expose types on diagnostics)
end
if __FILE__ == $0