This is a bug that was discovered during the push of #1403.
What happens is that since NativeArrays work only with boxed values, the copy_to operation could write data beyond its intended boundaries, hence corrupting random memory.
If you execute the test bundled with the PR, on my machine, with `--hardening` on, you get this error:
`BTD BUG: Dynamic type is Sys, static type is Array[Byte]`
What happens here is that the `dest` of the `memmove` was in a emplacement before the `Array[Byte]` itself, due to its length and because the `memmove` used val* as sizeof value, it rewrote the classid of `self`, hence changing its dynamic type effectively from `Array[Byte]` to `Sys`, which produces the typing bug.
If left too long to execute, or in an unlucky memory layout, it simply segfaulted.
The behaviour of NEW_NativeArray henceforth is that it will reserve space for n `val*` instead of the `ctype` of the values.
Pull-Request: #1417
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>
--- /dev/null
+bin/header_static:
+ mkdir -p bin
+ ../../../bin/nitc --dir bin src/header_static.nit
+
+tests: bin/header_static
+ cat CGGeometry.h | bin/header_static > static_CGGeometry.h
+ cat NSObject.h | bin/header_static > static_NSObject.h
--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Filters preprocessed C-like header files to remove static code and keep their signatures.
+#
+# This tool is used in the process of parsing header files to extract
+# information on the declared services (the functions and structures).
+# This information is then used to generate bindings for Nit code
+# to access these services.
+#
+# The C header sometimes contains static code. It deletes static code of
+# headers, but keep their signatures. This tool is an extension of
+# header_keeper. It searches the keyword static to identify
+# the static code, and ignores the code into their brackets. The result is
+# printed to sdtout.
+#
+# ~~~sh
+# cat Pre-Processed/CGGeometry.h | header_static > Pre-Processed/static_header.h
+# ~~~
+#
+# This module can also be used as a library.
+# The main service is the method `header_static`
+module header_static
+
+redef class Char
+ private fun is_endline: Bool do return "\};".has(self)
+end
+
+# Filters the preprocessed `input` to keep signatures for static code and write to the `output`
+fun header_static(input: Reader, output: Writer) do
+ var static_target = false
+ var static_attribute_target = false
+ var bracket_counter = 0
+ var previous_letter = ""
+ var instruction = ""
+ var double_underscore = 0
+ var position = 0
+
+ while not input.eof do
+ var line = input.read_line
+ if line.to_s.has("static") then static_target = true
+
+ if static_target then
+ if line.to_s.has("__attribute__") then static_attribute_target = true
+ for letter in line do
+ if letter == '{' then bracket_counter += 1
+ if letter == '}' then bracket_counter -= 1
+
+ if letter == '_' and previous_letter == "_" and bracket_counter == 0 then
+ double_underscore += 1
+ end
+
+ # Sometimes we lost space between return type and signature name,
+ # because he has a return line between both.
+ # We add a space before signature name for safety.
+ if bracket_counter == 0 and letter == '_' and double_underscore >= 1 and not static_attribute_target then
+ instruction = instruction.insert_at(" ", position - 2)
+ end
+ if bracket_counter == 0 and not letter.is_endline then instruction += letter.to_s
+ if bracket_counter == 0 and letter.is_endline then
+ instruction += ";"
+ static_target = false
+ static_attribute_target = false
+ end
+
+ if bracket_counter == 0 and (letter == '}' and double_underscore >= 1 or letter == ';') then
+ output.write instruction + "\n"
+ end
+
+ if letter.is_endline and bracket_counter == 0 then
+ double_underscore = 0
+ position = 0
+ instruction = ""
+ end
+
+ previous_letter = letter.to_s
+ position += 1
+ end
+ else
+ output.write line + "\n"
+ end
+ end
+end
+
+header_static(sys.stdin, sys.stdout)
var status_code = 0
# Receive body from request due to body callback registering
- redef fun body_callback(line: String)
- do
+ redef fun body_callback(line) do
self.body_str = "{self.body_str}{line}"
end
end
fun destroy do self.curl.destroy
# Header callback
- redef fun header_callback(line: String) do
+ redef fun header_callback(line) do
# We keep this callback silent for testing purposes
#if not line.has_prefix("Date:") then print "Header_callback : {line}"
end
# Body callback
- redef fun body_callback(line: String) do self.our_body = "{self.our_body}{line}"
+ redef fun body_callback(line) do self.our_body = "{self.our_body}{line}"
# Stream callback - Cf : No one is registered
- redef fun stream_callback(buffer: String, size: Int, count: Int) do print "Stream_callback : {buffer} - {size} - {count}"
+ redef fun stream_callback(buffer, size, count) do print "Stream_callback : {buffer} - {size} - {count}"
end
(self.back <= other.front and other.back <= self.front))
end
- redef fun padded(dist: N): Box3d[N] do return new Box3d[N].lrtbfb(left - dist, right + dist, top + dist, bottom - dist, front + dist, back - dist)
+ redef fun padded(dist): Box3d[N] do return new Box3d[N].lrtbfb(left - dist, right + dist, top + dist, bottom - dist, front + dist, back - dist)
end
# A 3d bounded object and an implementation of Boxed
private var data: Array[E] = new Array[E]
- redef fun add(item: E) do data.add(item)
- redef fun items_overlapping(item: Boxed[Numeric]): SimpleCollection[E]
+ redef fun add(item) do data.add(item)
+ redef fun items_overlapping(item): SimpleCollection[E]
do
var arr = new Array[E]
for i in data do
class Line[N: Numeric]
super ILine[N]
- redef var point_left: P
- redef var point_right: P
+ redef var point_left
+ redef var point_right
init
do
self.parent_node = parent
end
- redef fun items_overlapping(region :Boxed[Numeric]): SimpleCollection[E] do
+ redef fun items_overlapping(region): SimpleCollection[E] do
var res = new Array[E]
items_overlapping_in(region,res)
return res
end
# add the item to the tree, create children if the limit is reached
- redef fun add(item: E) do if self.is_leaf then self.data.add(item) else add_to_children(item)
+ redef fun add(item) do if self.is_leaf then self.data.add(item) else add_to_children(item)
private fun add_to_children(item: Boxed[Numeric])
do
end
end
- redef fun is_empty: Bool do return data.is_empty and (self.is_leaf or (child0.is_empty and child1.is_empty and child2.is_empty and child3.is_empty))
+ redef fun is_empty do return data.is_empty and (self.is_leaf or (child0.is_empty and child1.is_empty and child2.is_empty and child3.is_empty))
# Return whether or not the Node is a leaf of the tree
fun is_leaf: Bool do return child0 == null
# assert "123".to_json_value.to_s == "123"
# assert "true".to_json_value.to_s == "true"
# assert "[1, 2, 3]".to_json_value.to_s == "123"
- redef fun to_s: String
- do
+ redef fun to_s do
if value == null then return "null"
return value.to_s
end
#
# SEE: `create_node`
# SEE: `register`
- redef fun add(node: NeoNode) is abstract
+ redef fun add(node) is abstract
# Add a new node to the graph and return it.
#
redef fun to_s do return to_json
# Append the JSON representation of the node to the specified buffer.
- redef fun append_json_for(graph: NeoGraph, buffer: Buffer) do
+ redef fun append_json_for(graph, buffer) do
append_json(buffer)
end
end
# Append the JSON representation of the relationship to the specified buffer.
#
# Use the IDs specfied by `graph.nodes`.
- redef fun append_json_for(graph: NeoGraph, buffer: Buffer) do
+ redef fun append_json_for(graph, buffer) do
buffer.append "\{\"type\":"
rel_type.append_json(buffer)
buffer.append ",\"properties\":"
return nodes[id]
end
- redef fun has_id(id: Int): Bool do
+ redef fun has_id(id) do
return id >= 0 and id < nodes.length and nodes[id] isa NeoNode
end
end
# Get this reponse as a string according to HTTP protocol
- redef fun to_s: String
+ redef fun to_s
do
finalize
super Attributes
private var data = new Array[String]
- redef var length: Int = 0
+ redef var length = 0
- redef fun uri(index: Int): nullable String do
+ redef fun uri(index) do
if index >= 0 and index < length then
return data[index * 5]
else
end
end
- redef fun local_name(index: Int): nullable String do
+ redef fun local_name(index) do
if index >= 0 and index < length then
return data[index * 5 + 1]
else
end
end
- redef fun qname(index: Int): nullable String do
+ redef fun qname(index) do
if index >= 0 and index < length then
return data[index * 5 + 2]
else
# are not available.
#
# SEE: `length`
- redef fun type_of(index): nullable String do
+ redef fun type_of(index) do
if index isa Int then
if index >= 0 and index < length then
return data[index * 5 + 3]
# are not available.
#
# SEE: `length`
- redef fun value_of(index): nullable String do
+ redef fun value_of(index) do
if index isa Int then
if index >= 0 and index < length then
return data[index * 5 + 4]
#
# The index of the attribute, or -1 if it does not
# appear in the list.
- redef fun index_ns(uri: String, local_name: String): Int do
+ redef fun index_ns(uri, local_name) do
var i = 0
if "" != local_name then
#
# The index of the attribute, or -1 if it does not
# appear in the list.
- redef fun index_of(qname: String): Int do
+ redef fun index_of(qname) do
var i = 0
if "" != qname then
# The attribute type as a string, or `null` if the
# attribute is not in the list or if Namespace
# processing is not being performed.
- redef fun type_ns(uri: String, local_name: String): nullable String do
+ redef fun type_ns(uri, local_name) do
var i = 0
if "" != local_name then
# The attribute value as a string, or `null` if the
# attribute is not in the list or if Namespace
# processing is not being performed.
- redef fun value_ns(uri: String, local_name: String): nullable String do
+ redef fun value_ns(uri, local_name) do
var i = 0
if "" != local_name then
# can use it to make a persistent snapshot of a locator at any
# point during a document parse:
#
-# import sax::helpers::sax_locator_impl
-# import sax::content_handler
+# ~~~nitish
+# import sax::helpers::sax_locator_impl
+# import sax::content_handler
#
-# class Example super ContentHandler
-# private var locator: SAXLocator
-# private var start_loc: nullable SAXLocator = null
+# class Example super ContentHandler
+# private var locator: SAXLocator
+# private var start_loc: nullable SAXLocator = null
#
-# redef fun start_document do
-# # save the location of the start of the document
-# # for future use.
-# start_loc = new SAXLocatorImpl.from(locator)
-# end
+# redef fun start_document do
+# # save the location of the start of the document
+# # for future use.
+# start_loc = new SAXLocatorImpl.from(locator)
# end
+# end
+# ~~~
#
# Normally, parser writers will not use this class, since it
# is more efficient to provide location information only when
# Note: The original source code and documentation of this class comes, in part,
# from [SAX 2.0](http://www.saxproject.org).
class SAXLocatorImpl super SAXLocator
- redef var public_id: nullable String = null is writable
- redef var system_id: nullable String = null is writable
- redef var line_number: Int = -1 is writable
- redef var column_number: Int = -1 is writable
+ redef var public_id = null is writable
+ redef var system_id = null is writable
+ redef var line_number = -1 is writable
+ redef var column_number = -1 is writable
# Zero-argument constructor.
#
# XMLFilter
- redef var parent: nullable XMLReader = null is writable
+ redef var parent = null is writable
# XMLReader
- redef var entity_resolver: nullable EntityResolver = null is writable
- redef var dtd_handler: nullable DTDHandler = null is writable
- redef var content_handler: nullable ContentHandler = null is writable
- redef var error_handler: nullable ErrorHandler = null is writable
+ redef var entity_resolver = null is writable
+ redef var dtd_handler = null is writable
+ redef var content_handler = null is writable
+ redef var error_handler = null is writable
############################################################################
parent = parent_reader
end
- redef fun feature_recognized(name: String): Bool do
+ redef fun feature_recognized(name) do
if parent == null then
return false
else
end
end
- redef fun feature_readable(name: String): Bool do
+ redef fun feature_readable(name) do
if parent == null then
return false
else
end
end
- redef fun feature_writable(name: String): Bool do
+ redef fun feature_writable(name) do
if parent == null then
return false
else
# SEE: `feature_recognized`
#
# SEE: `feature_readable`
- redef fun feature(name: String): Bool do
+ redef fun feature(name) do
assert sax_recognized: parent != null else
sys.stderr.write("Feature: {name}\n")
end
# SEE: `feature_recognized`
#
# SEE: `feature_writable`
- redef fun feature=(name: String, value: Bool) do
+ redef fun feature=(name, value) do
assert sax_recognized: parent != null else
sys.stderr.write("Feature: {name}\n")
end
parent.feature(name) = value
end
- redef fun property_recognized(name: String): Bool do
+ redef fun property_recognized(name) do
if parent == null then
return false
else
end
end
- redef fun property_readable(name: String): Bool do
+ redef fun property_readable(name) do
if parent == null then
return false
else
end
end
- redef fun property_writable(name: String): Bool do
+ redef fun property_writable(name) do
if parent == null then
return false
else
# SEE: `property_recognized`
#
# SEE: `property_readable`
- redef fun property(name: String): nullable Object do
+ redef fun property(name) do
assert sax_recognized: parent != null else
sys.stderr.write("Property: {name}\n")
end
# SEE: `property_recognized`
#
# SEE: `property_writable`
- redef fun property=(name: String, value: nullable Object) do
+ redef fun property=(name, value) do
assert sax_recognized: parent != null else
sys.stderr.write("Property: {name}\n")
end
parent.property(name) = value
end
- redef fun parse(input: InputSource) do
+ redef fun parse(input) do
setup_parse
parent.parse(input)
end
- redef fun parse_file(system_id: String) do
+ redef fun parse_file(system_id) do
var source = new InputSource
source.system_id = system_id
############################################################################
# EntityResolver
- redef fun resolve_entity(public_id: nullable String,
- system_id: nullable String):
- nullable InputSource do
+ redef fun resolve_entity(public_id, system_id) do
if entity_resolver == null then
return null
else
############################################################################
# DTDHandler
- redef fun notation_decl(name: String, public_id: String,
- system_id: String) do
+ redef fun notation_decl(name, public_id, system_id) do
if dtd_handler != null then
dtd_handler.notation_decl(name, public_id, system_id)
end
end
- redef fun unparsed_entity_decl(name: String, public_id: String,
- system_id: String) do
+ redef fun unparsed_entity_decl(name, public_id, system_id) do
if dtd_handler != null then
dtd_handler.unparsed_entity_decl(name, public_id, system_id)
end
############################################################################
# ContentHandler
- redef fun document_locator=(locator: SAXLocator) do
+ redef fun document_locator=(locator) do
if content_handler != null then
content_handler.document_locator = locator
end
end
end
- redef fun start_prefix_mapping(prefix: String, uri: String) do
+ redef fun start_prefix_mapping(prefix, uri) do
if content_handler != null then
content_handler.start_prefix_mapping(prefix, uri)
end
end
- redef fun end_prefix_mapping(prefix: String) do
+ redef fun end_prefix_mapping(prefix) do
if content_handler != null then
content_handler.end_prefix_mapping(prefix)
end
end
- redef fun start_element(uri: String, local_name: String, qname: String,
- atts: Attributes) do
+ redef fun start_element(uri, local_name, qname, atts) do
if content_handler != null then
content_handler.start_element(uri, local_name, qname, atts)
end
end
- redef fun end_element(uri: String, local_name: String, qname: String) do
+ redef fun end_element(uri, local_name, qname) do
if content_handler != null then
content_handler.end_element(uri, local_name, qname)
end
end
- redef fun characters(str: String) do
+ redef fun characters(str) do
if content_handler != null then
content_handler.characters(str)
end
end
- redef fun ignorable_whitespace(str: String) do
+ redef fun ignorable_whitespace(str) do
if content_handler != null then
content_handler.ignorable_whitespace(str)
end
end
- redef fun processing_instruction(target: String, data: nullable String) do
+ redef fun processing_instruction(target, data) do
if content_handler != null then
content_handler.processing_instruction(target, data)
end
end
- redef fun skipped_entity(name: String) do
+ redef fun skipped_entity(name) do
if content_handler != null then
content_handler.skipped_entity(name)
end
############################################################################
# ErrorHandler
- redef fun warning(exception: SAXParseException) do
+ redef fun warning(exception) do
if error_handler != null then
error_handler.warning(exception)
end
end
- redef fun error(exception: SAXParseException) do
+ redef fun error(exception) do
if error_handler != null then
error_handler.error(exception)
end
end
- redef fun fatal_error(exception: SAXParseException) do
+ redef fun fatal_error(exception) do
if error_handler != null then
error_handler.fatal_error(exception)
else
private var model = new XophonReaderModel
private var lexer: XophonLexer is noinit
- redef fun entity_resolver: nullable EntityResolver do return model.entity_resolver
- redef fun entity_resolver=(entity_resolver: nullable EntityResolver) do
+ redef fun entity_resolver do return model.entity_resolver
+ redef fun entity_resolver=(entity_resolver) do
model.entity_resolver = entity_resolver
end
- redef fun dtd_handler: nullable DTDHandler do return model.dtd_handler
- redef fun dtd_handler=(dtd_handler: nullable DTDHandler) do
+ redef fun dtd_handler do return model.dtd_handler
+ redef fun dtd_handler=(dtd_handler) do
model.dtd_handler = dtd_handler
end
- redef fun content_handler: nullable ContentHandler do return model.content_handler
- redef fun content_handler=(content_handler: nullable ContentHandler) do
+ redef fun content_handler do return model.content_handler
+ redef fun content_handler=(content_handler) do
model.content_handler = content_handler
end
- redef fun error_handler: nullable ErrorHandler do return model.error_handler
- redef fun error_handler=(error_handler: nullable ErrorHandler) do
+ redef fun error_handler do return model.error_handler
+ redef fun error_handler=(error_handler) do
model.error_handler = error_handler
end
- redef fun feature_recognized(name: String): Bool do
+ redef fun feature_recognized(name) do
return model.feature_recognized(name)
end
- redef fun feature_readable(name: String): Bool do
+ redef fun feature_readable(name) do
return model.feature_readable(name)
end
- redef fun feature_writable(name: String): Bool do
+ redef fun feature_writable(name) do
return model.feature_readable(name)
end
- redef fun feature(name: String): Bool do return model.feature(name)
- redef fun feature=(name: String, value: Bool) do model.feature(name) = value
+ redef fun feature(name) do return model.feature(name)
+ redef fun feature=(name, value) do model.feature(name) = value
- redef fun property_recognized(name: String): Bool do
+ redef fun property_recognized(name) do
return model.property_recognized(name)
end
- redef fun property_readable(name: String): Bool do
+ redef fun property_readable(name) do
return model.property_readable(name)
end
- redef fun property_writable(name: String): Bool do
+ redef fun property_writable(name) do
return model.property_writable(name)
end
- redef fun property(name: String): nullable Object do
+ redef fun property(name) do
return model.property(name)
end
- redef fun property=(name: String, value: nullable Object) do
+ redef fun property=(name, value) do
model.property(name) = value
end
- redef fun parse(input: InputSource) do
+ redef fun parse(input) do
var system_id: nullable MaybeError[String, Error] = null
model.locator = new SAXLocatorImpl
end
end
- redef fun parse_file(system_id: String) do
+ redef fun parse_file(system_id) do
parse(new InputSource.with_system_id(system_id))
end
############################################################################
# XMLReader
- redef fun property(name: String): nullable Object do
+ redef fun property(name) do
assert sax_recognized: parent != null else
sys.stderr.write("Property: {name}\n")
end
end
end
- redef fun property=(name: String, value: nullable Object) do
+ redef fun property=(name, value) do
assert sax_recognized: parent != null else
sys.stderr.write("Property: {name}\n")
end
end
end
- redef fun parse(input: InputSource) do
+ redef fun parse(input) do
assert parent_is_not_null: parent != 0 else
sys.stderr.write("No parent for filter.")
end
############################################################################
# EntityResolver
- redef fun resolve_entity(public_id: nullable String,
- system_id: nullable String):
- nullable InputSource do
+ redef fun resolve_entity(public_id, system_id) do
log.push(["resolve_entity",
public_id or else "^NULL",
system_id or else "^NULL"])
############################################################################
# DTDHandler
- redef fun notation_decl(name: String, public_id: String,
- system_id: String) do
+ redef fun notation_decl(name, public_id, system_id) do
log.push(["notation_decl", name, public_id, system_id])
super
end
- redef fun unparsed_entity_decl(name: String, public_id: String,
- system_id: String) do
+ redef fun unparsed_entity_decl(name, public_id, system_id) do
log.push(["unparsed_entity_decl", name, public_id, system_id])
super
end
############################################################################
# ContentHandler
- redef fun document_locator=(locator: SAXLocator) do
+ redef fun document_locator=(locator) do
log.push(["document_locator=",
locator.public_id or else "^NULL",
locator.system_id or else "^NULL",
super
end
- redef fun start_prefix_mapping(prefix: String, uri: String) do
+ redef fun start_prefix_mapping(prefix, uri) do
log.push(["start_prefix_mapping", prefix, uri])
super
end
- redef fun end_prefix_mapping(prefix: String) do
+ redef fun end_prefix_mapping(prefix) do
log.push(["end_prefix_mapping", prefix])
super
end
- redef fun start_element(uri: String, local_name: String, qname: String,
- atts: Attributes) do
+ redef fun start_element(uri, local_name, qname, atts) do
var entry = new Array[String]
var i = 0
var length = atts.length
super
end
- redef fun end_element(uri: String, local_name: String, qname: String) do
+ redef fun end_element(uri, local_name, qname) do
log.push(["end_element", uri, local_name, qname])
super
end
- redef fun characters(str: String) do
+ redef fun characters(str) do
log.push(["characters", str])
super
end
- redef fun ignorable_whitespace(str: String) do
+ redef fun ignorable_whitespace(str) do
log.push(["ignorable_witespace", str])
super
end
- redef fun processing_instruction(target: String, data: nullable String) do
+ redef fun processing_instruction(target, data) do
log.push(["processing_instruction", target, data or else "^NULL"])
super
end
- redef fun skipped_entity(name: String) do
+ redef fun skipped_entity(name) do
log.push(["skipped_entity", name])
super
end
############################################################################
# ErrorHandler
- redef fun warning(exception: SAXParseException) do
+ redef fun warning(exception) do
log.push(["warning", exception.full_message])
super
end
- redef fun error(exception: SAXParseException) do
+ redef fun error(exception) do
log.push(["error", exception.full_message])
super
end
- redef fun fatal_error(exception: SAXParseException) do
+ redef fun fatal_error(exception) do
log.push(["fatal_error", exception.full_message])
if error_handler != null then
error_handler.fatal_error(exception)
############################################################################
# DeclHandler
- redef fun element_decl(name: String, model: String) do
+ redef fun element_decl(name, model) do
log.push(["element_decl", name, model])
if decl_handler != null then
decl_handler.element_decl(name, model)
end
end
- redef fun attribute_decl(element_name: String,
- attribute_name: String,
- attribute_type: String,
- mode: nullable String,
- value: nullable String) do
+ redef fun attribute_decl(element_name, attribute_name, attribute_type, mode, value) do
log.push(["attribute_decl",
element_name,
attribute_name,
end
end
- redef fun internal_entity_decl(name: String, value: String) do
+ redef fun internal_entity_decl(name, value) do
log.push(["internal_entity_decl", name, value])
if decl_handler != null then
decl_handler.internal_entity_decl(name, value)
end
end
- redef fun external_entity_decl(name: String, value: String) do
+ redef fun external_entity_decl(name, value) do
log.push(["external_entity_decl", name, value])
if decl_handler != null then
decl_handler.external_entity_decl(name, value)
############################################################################
# LexicalHandler
- redef fun start_dtd(name: String, public_id: nullable String,
- system_id: nullable String) do
+ redef fun start_dtd(name, public_id, system_id) do
log.push(["start_dtd", name,
public_id or else "^NULL",
system_id or else "^NULL"])
end
end
- redef fun start_entity(name: String) do
+ redef fun start_entity(name) do
log.push(["start_entity", name])
if lexical_handler != null then
lexical_handler.start_entity(name)
end
end
- redef fun end_entity(name: String) do
+ redef fun end_entity(name) do
log.push(["end_entity", name])
if lexical_handler != null then
lexical_handler.end_entity(name)
end
end
- redef fun comment(str: String) do
+ redef fun comment(str) do
log.push(["comment", str])
if lexical_handler != null then
lexical_handler.comment(str)
end
# If socket.end_reached, nothing will happen
- redef fun write(msg: Text)
+ redef fun write(msg)
do
if closed then return
socket.write(msg.to_s)
new done `{ return SQLITE_DONE; `} # 101 /* sqlite3_step() has finished executing */
fun is_done: Bool `{ return self == SQLITE_DONE; `}
- redef fun to_s: String import NativeString.to_s `{
+ redef fun to_s import NativeString.to_s `{
#if SQLITE_VERSION_NUMBER >= 3007015
char *err = (char *)sqlite3_errstr(self);
#else
redef var item: StatementRow is noinit
- redef var is_ok: Bool is noinit
+ redef var is_ok is noinit
# require: `self.statement.is_open`
redef fun next
private var items: NativeString
# Number of bytes in the array
- redef var length: Int
+ redef var length
# Capacity of the array
private var capacity: Int
# var b = new Bytes.empty
# b.add 101
# assert b[0] == 101
- redef fun [](i: Int): Int do
+ redef fun [](i) do
assert i >= 0
assert i < length
return items[i].ascii
# var b = new Bytes.with_capacity(1)
# b[0] = 101
# assert b.to_s == "e"
- redef fun []=(i: Int, v: Int) do
+ redef fun []=(i, v) do
if persisted then regen
assert i >= 0
assert i <= length
# var b = new Bytes.empty
# b.add 101
# assert b.to_s == "e"
- redef fun add(c: Int) do
+ redef fun add(c) do
if persisted then regen
if length >= capacity then
enlarge(length)
# var b = new Bytes.empty
# b.append([104, 101, 108, 108, 111])
# assert b.to_s == "hello"
- redef fun append(arr: Collection[Int]) do
+ redef fun append(arr) do
if arr isa Bytes then
append_ns(arr.items, arr.length)
else
var tgt: NativeString
- redef var index: Int
+ redef var index
var max: Int
redef fun next do is_ok = false
- redef var is_ok: Bool = true
+ redef var is_ok = true
var container: Container[E]
end
private class CoupleMapIterator[K, V]
super MapIterator[K, V]
redef fun item do return _iter.item.second
-
+
#redef fun item=(e) do _iter.item.second = e
redef fun key do return _iter.item.first
#
# This file is free software, which comes along with NIT. This software is
# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. You can modify it is you want, provided this header
# is kept unaltered, and a notification of the changes is added.
# You are allowed to redistribute it and sell it, alone or is a part of
redef fun last_index_of(item) do return last_index_of_from(item, length-1)
- redef fun index_of_from(item, pos)
- do
+ redef fun index_of_from(item, pos) do
var i = pos
var len = length
while i < len do
return -1
end
- redef fun last_index_of_from(item, pos)
- do
+ redef fun last_index_of_from(item, pos) do
var i = pos
while i >= 0 do
if self[i] == item then
self[0] = item
end
- redef fun insert(item: E, pos: Int)
- do
+ redef fun insert(item, pos) do
enlarge(length + 1)
copy_to(pos, length-pos, self, pos + 1)
self[pos] = item
class Range[E: Discrete]
super Collection[E]
- redef var first: E
+ redef var first
# Get the last element.
var last: E
# s.add(1)
# assert s.has(1)
# assert not s.has(2)
- redef fun has(e)
- do
+ redef fun has(e) do
return nodes.has_key(e)
end
# Initially it is in its own disjoint subset
#
# ENSURE: `has(e)`
- redef fun add(e:E)
- do
+ redef fun add(e) do
if nodes.has_key(e) then return
var ne = new DisjointSetNode
nodes[e] = ne
end
# End of file?
- redef var end_reached: Bool = false
+ redef var end_reached = false
# Open the file at `path` for reading.
#
prepare_buffer(1)
end
- redef fun poll_in: Bool is extern "file_stdin_poll_in"
+ redef fun poll_in is extern "file_stdin_poll_in"
end
# Standard output stream.
#
# This file is free software, which comes along with NIT. This software is
# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. You can modify it is you want, provided this header
# is kept unaltered, and a notification of the changes is added.
# You are allowed to redistribute it and sell it, alone or is a part of
type OTHER: Comparable
# Is `self` lesser than `other`?
- fun <(other: OTHER): Bool is abstract
+ fun <(other: OTHER): Bool is abstract
# not `other` < `self`
# Note, the implementation must ensure that: `(x<=y) == (x<y or x==y)`
redef fun !=(i) is intern
redef fun output is intern
- redef fun <=(i): Bool is intern
- redef fun <(i): Bool is intern
- redef fun >=(i): Bool is intern
- redef fun >(i): Bool is intern
+ redef fun <=(i) is intern
+ redef fun <(i) is intern
+ redef fun >=(i) is intern
+ redef fun >(i) is intern
redef fun +(i) is intern
redef fun - is intern
redef fun is_between(c, d)
do
- if self < c or d < self then
+ if self < c or d < self then
return false
- else
+ else
return true
end
end
# count digits
while n > 0 do
d += 1
- n = n / b # euclidian division /
+ n = n / b # euclidian division /
end
return d
end
private class Concat
super RopeString
- redef var length: Int is noinit
+ redef var length is noinit
redef fun substrings do return new RopeSubstrings(self)
end
redef fun copy_to_native(dest, n, src_offset, dest_offset) do
- var remlen = n
var subs = new RopeSubstrings.from(self, src_offset)
var st = src_offset - subs.pos
var off = dest_offset
# Maximum position iterable.
var maxpos: Int
- redef var index: Int
+ redef var index
# Init the iterator from a RopeBuffer.
init(t: RopeBuffer) is old_style_init do
# Current position in `ns`.
var pns: Int
- redef var index: Int
+ redef var index
# Init the iterator from a RopeBuffer.
init(tgt: RopeBuffer) is old_style_init do
#
# REQUIRE: `n` must be large enough to contain `len` bytes
#
- # var ns = new NativeString(8)
- # "Text is String".copy_to_native(ns, 8, 2, 0)
+ # var ns = new NativeString(8)
+ # "Text is String".copy_to_native(ns, 8, 2, 0)
# assert ns.to_s_with_length(8) == "xt is St"
#
fun copy_to_native(dest: NativeString, n, src_offset, dest_offset: Int) do
# copy locally the char* as Nit Strings are immutable.
private fun fast_cstring: NativeString is abstract
- redef var length: Int = 0
+ redef var length = 0
redef fun output
do
# Indes in _items of the last item of the string
private var index_to: Int is noinit
- redef var chars: SequenceRead[Char] = new FlatStringCharView(self) is lazy
+ redef var chars = new FlatStringCharView(self) is lazy
redef fun [](index)
do
index_to = to
end
- redef fun to_cstring: NativeString
- do
+ redef fun to_cstring do
if real_items != null then
return real_items.as(not null)
else
capacity = c
end
- redef fun to_s: String
- do
+ redef fun to_s do
written = true
if length == 0 then items = new NativeString(1)
return new FlatString.with_infos(items, length, 0, length - 1)
return to_s_with_length(len)
end
- redef fun to_s_with_length(len: Int): FlatString
+ redef fun to_s_with_length(len)
do
var real_len = new Container[Int](0)
var x = make_index(len, real_len)
redef type OTHER: FlatString
# Length in bytes of the string (e.g. the length of the C string)
- redef var bytelen: Int
+ redef var bytelen
# Cache for the last accessed character in the char
var cache = new CharCache(-1,-1)
end
# O(n)
- redef fun substring(from: Int, count: Int) do
+ redef fun substring(from, count) do
assert count >= 0
if from < 0 then
redef class FlatBuffer
- redef var bytelen: Int
+ redef var bytelen
redef init from(s) do
if s isa Concat then
return to_s_with_length(len)
end
- redef fun to_s_with_length(len: Int): FlatString
+ redef fun to_s_with_length(len)
do
return new FlatString.with_bytelen(self, 0, len - 1, len)
end
end
# Do the full rendering and write the final content to a stream
- redef fun write_to(stream: Writer)
+ redef fun write_to(stream)
do
assert not is_writing
is_writing = true
# It is a placeholder to share data between each phase.
class DocModel
- # `DocPage` composing the documentation.
+ # `DocPage` composing the documentation associated to their ids.
#
# This is where `DocPhase` store and access pages to produce documentation.
- var pages = new Array[DocPage]
+ #
+ # See `add_page`.
+ var pages: Map[String, DocPage] = new HashMap[String, DocPage]
# Nit `Model` from which we extract the documentation.
var model: Model is writable
# The entry point of the `model`.
var mainmodule: MModule is writable
+
+ # Add a `page` to this documentation.
+ fun add_page(page: DocPage) do
+ if pages.has_key(page.id) then
+ print "Warning: multiple page with the same id `{page.id}`"
+ end
+ pages[page.id] = page
+ end
end
# A documentation page abstraction.
# the page.
class DocPage
+ # Page uniq id.
+ #
+ # The `id` is used as name for the generated file corresponding to the page
+ # (if any).
+ # Because multiple pages can be generated in the same directory it should be
+ # uniq.
+ #
+ # The `id` can also be used to establish links between pages (HTML links,
+ # HTML anchors, vim links, etc.).
+ var id: String is writable
+
# Title of this page.
var title: String is writable
end
redef class MEntity
+ # ID used as a unique ID and in file names.
+ #
+ # **Must** match the following (POSIX ERE) regular expression:
+ #
+ # ~~~POSIX ERE
+ # ^[A-Za-z_][A-Za-z0-9._-]*$
+ # ~~~
+ #
+ # That way, the ID is always a valid URI component and a valid XML name.
+ fun nitdoc_id: String do return full_name.to_cmangle
+
# Name displayed in console for debug and tests.
fun nitdoc_name: String do return name.html_escape
end
+redef class MModule
+
+ # Avoid id conflict with group
+ redef fun nitdoc_id do
+ if mgroup == null then return super
+ return "{mgroup.full_name}::{full_name}".to_cmangle
+ end
+end
+
redef class MClassDef
redef fun nitdoc_name do return mclass.nitdoc_name
end
# Populates the given DocModel.
redef fun apply do
- for page in doc.pages do page.build_concerns(doc)
+ for page in doc.pages.values do page.build_concerns(doc)
end
end
module doc_console
import semantize
+import doc_extract
import doc::console_templates
# Nitx handles console I/O.
# Pretty prints the results for the console.
fun make_results(nitx: Nitx, results: Array[NitxMatch]): DocPage do
- var page = new DocPage("Results")
+ var page = new DocPage("results", "Results")
page.root.add_child(new QueryResultArticle(self, results))
return page
end
redef fun perform(nitx, doc) do
var name = args.first
var res = new Array[NitxMatch]
- for mentity in doc.search_mentities(name) do
+ for mentity in doc.mentities_by_name(name) do
res.add new MEntityMatch(self, mentity)
end
return res
if len == 1 then
var res = results.first.as(MEntityMatch)
var mentity = res.mentity
- var page = new DocPage("Results")
+ var page = new DocPage("resultats", "Results")
var article = new DefinitionArticle(mentity)
article.cs_title = mentity.name
article.cs_subtitle = mentity.cs_declaration
redef fun perform(nitx, doc) do
var res = new Array[NitxMatch]
var name = args.first
- for page in doc.pages do
+ for page in doc.pages.values do
if name == "*" then # FIXME dev only
res.add new PageMatch(self, page)
else if page.title == name then
return res
end
# else, lookup the model by name
- for mentity in doc.search_mentities(name) do
+ for mentity in doc.mentities_by_name(name) do
if mentity isa MClass then continue
if mentity isa MProperty then continue
res.add new CodeMatch(self, mentity.cs_location, mentity.cs_source_code)
end
redef fun make_results(nitx, results) do
- var page = new DocPage("Code Results")
+ var page = new DocPage("results", "Code Results")
for res in results do
page.add new CodeQueryArticle(self, res.as(CodeMatch))
end
## exploration
-redef class DocModel
-
- # Lists all MEntities in the model.
- private var mentities: Collection[MEntity] is lazy do
- var res = new HashSet[MEntity]
- res.add_all mprojects
- res.add_all mgroups
- res.add_all mmodules
- res.add_all mclasses
- res.add_all mclassdefs
- res.add_all mproperties
- res.add_all mpropdefs
- return res
- end
-
- # Search MEntities that match `name` by their name or namespace.
- private fun search_mentities(name: String): Array[MEntity] do
- var res = new Array[MEntity]
- for mentity in mentities do
- if mentity.name != name and mentity.cs_namespace != name then continue
- res.add mentity
- end
- return res
- end
-end
-
# Visitor looking for initialized `MType` (new T).
#
# See `NewQuery`.
end
end
end
+
+ # Lists all MEntities in the model.
+ #
+ # FIXME invalidate cache if `self` is modified.
+ var mentities: Collection[MEntity] is lazy do
+ var res = new HashSet[MEntity]
+ res.add_all mprojects
+ res.add_all mgroups
+ res.add_all mmodules
+ res.add_all mclasses
+ res.add_all mclassdefs
+ res.add_all mproperties
+ res.add_all mpropdefs
+ return res
+ end
+
+ # Searches MEntities that match `name`.
+ fun mentities_by_name(name: String): Array[MEntity] do
+ var res = new Array[MEntity]
+ for mentity in mentities do
+ if mentity.name != name then continue
+ res.add mentity
+ end
+ return res
+ end
+
+ # Looks up a MEntity by its `namespace`.
+ #
+ # Usefull when `mentities_by_name` by return conflicts.
+ #
+ # Path can be the shortest possible to disambiguise like `Class::property`.
+ # In case of larger conflicts, a more complex namespace can be given like
+ # `project::module::Class::prop`.
+ fun mentities_by_namespace(namespace: String): Array[MEntity] do
+ var res = new Array[MEntity]
+ for mentity in mentities do
+ mentity.mentities_by_namespace(namespace, res)
+ end
+ return res
+ end
+end
+
+redef class MEntity
+ # Looks up a MEntity by its `namespace` from `self`.
+ private fun mentities_by_namespace(namespace: String, res: Array[MEntity]) do end
+
+ private fun lookup_in(mentities: Collection[MEntity], namespace: String, res: Array[MEntity]) do
+ var parts = namespace.split_once_on("::")
+ var name = parts.shift
+ for mentity in mentities do
+ if mentity.name != name then continue
+ if parts.is_empty then
+ res.add mentity
+ else
+ mentity.mentities_by_namespace(parts.first, res)
+ end
+ end
+ end
+end
+
+redef class MProject
+ redef fun mentities_by_namespace(namespace, res) do lookup_in(mgroups, namespace, res)
+end
+
+redef class MGroup
+ redef fun mentities_by_namespace(namespace, res) do lookup_in(mmodules, namespace, res)
+end
+
+redef class MModule
+ redef fun mentities_by_namespace(namespace, res) do lookup_in(mclassdefs, namespace, res)
+end
+
+redef class MClassDef
+ redef fun mentities_by_namespace(namespace, res) do lookup_in(mpropdefs, namespace, res)
end
redef fun apply do
if ctx.opt_nodot.value then return
- for page in doc.pages do
+ for page in doc.pages.values do
var article = page.build_graph(self, doc)
if article == null then continue
# FIXME avoid diff
var name_sorter = new MEntityNameSorter
redef fun apply do
- for page in doc.pages do
+ for page in doc.pages.values do
if page isa MEntityPage then page.build_inh_list(self, doc)
end
end
redef fun apply do
init_output_dir
- for page in doc.pages do
+ for page in doc.pages.values do
page.render(self, doc).write_to_file("{ctx.output_dir.to_s}/{page.html_url}")
end
end
# all properties below are roughly copied from `doc_pages`
# Build page title string
- fun init_title(v: RenderHTMLPhase, doc: DocModel) is abstract
+ fun init_title(v: RenderHTMLPhase, doc: DocModel) do end
# Build top menu template if any.
fun init_topmenu(v: RenderHTMLPhase, doc: DocModel) do
super DocPhase
redef fun apply do
- for page in doc.pages do
+ for page in doc.pages.values do
if not page isa MEntityPage then continue
page.root.build_intro_redef_list(self, doc, page)
end
private var lin_sorter = new MEntityNameSorter
redef fun apply do
- for page in doc.pages do page.apply_linearization(self, doc)
+ for page in doc.pages.values do page.apply_linearization(self, doc)
end
end
# Instanciates documentation pages for the given DocModel.
redef fun apply do
- doc.pages.add new OverviewPage("Overview")
- doc.pages.add new SearchPage("Index")
+ doc.add_page new OverviewPage("overview", "Overview")
+ doc.add_page new SearchPage("search", "Index")
for mgroup in doc.mgroups do
- doc.pages.add new MGroupPage(mgroup.nitdoc_name, mgroup)
+ doc.add_page new MGroupPage(mgroup)
end
for mmodule in doc.mmodules do
- doc.pages.add new MModulePage(mmodule.nitdoc_name, mmodule)
+ doc.add_page new MModulePage(mmodule)
end
for mclass in doc.mclasses do
- doc.pages.add new MClassPage(mclass.nitdoc_name, mclass)
+ doc.add_page new MClassPage(mclass)
end
for mproperty in doc.mproperties do
- doc.pages.add new MPropertyPage(mproperty.nitdoc_name, mproperty)
+ doc.add_page new MPropertyPage(mproperty)
end
end
end
# A DocPage documenting a MEntity.
class MEntityPage
+ autoinit mentity
super DocPage
# Type of MEntity documented by this page.
# MEntity documented by this page.
var mentity: MENTITY
+
+ redef var id is lazy do return mentity.nitdoc_id
+ redef var title is lazy do return mentity.nitdoc_name
end
# A documentation page about a MGroup.
# Populates the given DocModel.
redef fun apply do
- for page in doc.pages do
+ for page in doc.pages.values do
if page isa MEntityPage then page.build_poset(self, doc)
end
end
# Populates the given DocModel.
redef fun apply do
- for page in doc.pages do page.apply_structure(self, doc)
+ for page in doc.pages.values do page.apply_structure(self, doc)
end
end
import ordered_tree
redef class MEntity
- # ID used as a HTML unique ID and in file names.
- #
- # **Must** match the following (POSIX ERE) regular expression:
- #
- # ~~~POSIX ERE
- # ^[A-Za-z_][A-Za-z0-9._-]*$
- # ~~~
- #
- # That way, the ID is always a valid URI component and a valid XML name.
- fun nitdoc_id: String is abstract
-
# URL of this entity’s Nitdoc page.
fun nitdoc_url: String is abstract
writable
autoinit
noautoinit
+lateinit
nosuper
old_style_init
abstract
var mreadpropdef = npropdef.mreadpropdef
if mreadpropdef == null or mreadpropdef.msignature == null then return # Skip broken attribute
if npropdef.noinit then continue # Skip noinit attribute
- var atautoinit = npropdef.get_single_annotation("autoinit", self)
- if atautoinit != null then
- # For autoinit attributes, call the reader to force
+ var atlateinit = npropdef.get_single_annotation("lateinit", self)
+ if atlateinit != null then
+ # For lateinit attributes, call the reader to force
# the lazy initialization of the attribute.
initializers.add(mreadpropdef.mproperty)
mreadpropdef.mproperty.is_autoinit = true
return true
end
+ # Checks for useless type in redef signatures.
+ private fun check_repeated_types(modelbuilder: ModelBuilder) do end
end
redef class ASignature
var nt = nsig.n_type
if nt != null then modelbuilder.check_visibility(nt, nt.mtype.as(not null), mpropdef)
end
+ check_repeated_types(modelbuilder)
+ end
+
+ # For parameters, type is always useless in a redef.
+ # For return type, type is useless if not covariant with introduction.
+ redef fun check_repeated_types(modelbuilder) do
+ if mpropdef.is_intro or n_signature == null then return
+ # check params
+ for param in n_signature.n_params do
+ if param.n_type != null then
+ modelbuilder.advice(param.n_type, "useless-signature", "Warning: useless type repetition on parameter `{param.n_id.text}` for redefined method `{mpropdef.name}`")
+ end
+ end
+ # get intro
+ var intro = mpropdef.mproperty.intro
+ var n_intro = modelbuilder.mpropdef2npropdef.get_or_null(intro)
+ if n_intro == null or not n_intro isa AMethPropdef then return
+ # check return type
+ var ret_type = n_signature.ret_type
+ if ret_type != null and ret_type == n_intro.n_signature.ret_type then
+ modelbuilder.advice(n_signature.n_type, "useless-signature", "Warning: useless return type repetition for redefined method `{mpropdef.name}`")
+ end
end
end
end
var atlazy = self.get_single_annotation("lazy", modelbuilder)
- var atautoinit = self.get_single_annotation("autoinit", modelbuilder)
- if atlazy != null or atautoinit != null then
- if atlazy != null and atautoinit != null then
- modelbuilder.error(atlazy, "Error: `lazy` incompatible with `autoinit`.")
+ var atlateinit = self.get_single_annotation("lateinit", modelbuilder)
+ if atlazy != null or atlateinit != null then
+ if atlazy != null and atlateinit != null then
+ modelbuilder.error(atlazy, "Error: `lazy` incompatible with `lateinit`.")
return
end
if not has_value then
if atlazy != null then
modelbuilder.error(atlazy, "Error: `lazy` attributes need a value.")
- else if atautoinit != null then
- modelbuilder.error(atautoinit, "Error: `autoinit` attributes need a value.")
+ else if atlateinit != null then
+ modelbuilder.error(atlateinit, "Error: `lateinit` attributes need a value.")
end
has_value = true
return
if mlazypropdef != null then
mlazypropdef.static_mtype = modelbuilder.model.get_mclasses_by_name("Bool").first.mclass_type
end
+ check_repeated_types(modelbuilder)
end
redef fun check_signature(modelbuilder)
end
end
end
+
+ # Type is useless if the attribute type is the same thant the intro.
+ redef fun check_repeated_types(modelbuilder) do
+ if mreadpropdef.is_intro or n_type == null then return
+ # get intro
+ var intro = mreadpropdef.mproperty.intro
+ var n_intro = modelbuilder.mpropdef2npropdef.get_or_null(intro)
+ if n_intro == null then return
+ # get intro type
+ var ntype = null
+ if n_intro isa AMethPropdef then
+ ntype = n_intro.n_signature.ret_type
+ else if n_intro isa AAttrPropdef and n_intro.n_type != null then
+ ntype = n_intro.n_type.mtype
+ end
+ # check
+ if ntype ==null or ntype != n_type.mtype then return
+ modelbuilder.advice(n_type, "useless-signature", "Warning: useless type repetition on redefined attribute `{mpropdef.name}`")
+ end
end
redef class ATypePropdef
# A model builder to parse files
var modelbuilder = new ModelBuilder(model, toolcontext)
-# Here we load an process all modules passed on the command line
+# Here we load and process all modules passed on the command line
var mmodules = modelbuilder.parse_full(arguments)
toolcontext.mmodules_to_check.add_all mmodules
var b: Object is noautoinit
#alt1#var b2: Object = get(-4) is noautoinit
var c: Object is noautoinit
- var d: Object = get(2) is autoinit
- #alt2#var d2: Object = get(-2) is autoinit, lazy
+ var d: Object = get(2) is lateinit
+ #alt2#var d2: Object = get(-2) is lateinit, lazy
var e: Object = get(1)
fun setc(v: Object) is autoinit do self.c = get(v)
init do
--- /dev/null
+--no-color -W test_advice_repeated_types.nit
-alt/base_init_autoinit2_alt2.nit:23,40--43: Error: `lazy` incompatible with `autoinit`.
+alt/base_init_autoinit2_alt2.nit:23,40--43: Error: `lazy` incompatible with `lateinit`.
--- /dev/null
+../lib/standard/bytes.nit:51,7--19: Documentation warning: Undocumented property `with_capacity`
+../lib/standard/bytes.nit:164,6--13: Documentation warning: Undocumented property `to_bytes`
+../lib/standard/stream.nit:425,6--17: Documentation warning: Undocumented property `buffer_reset`
+../lib/standard/file.nit:444,6--19: Documentation warning: Undocumented property `read_all_bytes`
+test_advice_repeated_types.nit:36,15--20: Warning: useless type repetition on redefined attribute `_a`
+test_advice_repeated_types.nit:37,18--20: Warning: useless type repetition on parameter `b1` for redefined method `b`
+test_advice_repeated_types.nit:38,18--20: Warning: useless type repetition on parameter `c1` for redefined method `c`
+test_advice_repeated_types.nit:38,27--29: Warning: useless type repetition on parameter `c2` for redefined method `c`
+test_advice_repeated_types.nit:39,15--20: Warning: useless return type repetition for redefined method `d`
+test_advice_repeated_types.nit:40,18--20: Warning: useless type repetition on parameter `e1` for redefined method `e`
+test_advice_repeated_types.nit:40,24--29: Warning: useless return type repetition for redefined method `e`
+test_advice_repeated_types.nit:49,18--20: Warning: useless type repetition on parameter `e1` for redefined method `e`
-Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:960)
+Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:957)
NativeString
N
Nit
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class A
+ var a: Object
+ fun b(b1: Int) is abstract
+ fun c(c1: Int, c2: Int) is abstract
+ fun d: Object is abstract
+ fun e(e1: Int): Object is abstract
+end
+
+class B
+ super A
+
+ redef var a
+ redef fun b(b1) do end
+ redef fun c(c1, c2) do end
+ redef fun d do return ""
+ redef fun e(e1) do return ""
+end
+
+class C
+ super A
+
+ redef var a: Object
+ redef fun b(b1: Int) do end
+ redef fun c(c1: Int, c2: Int) do end
+ redef fun d: Object do return ""
+ redef fun e(e1: Int): Object do return ""
+end
+
+class D
+ super A
+
+ redef fun b(b1) do end
+ redef fun c(c1, c2) do end
+ redef fun d: Int do return 1
+ redef fun e(e1: Int): Numeric do return 1
+end
+
+class E
+ super A
+
+ redef var d: Int = 1
+end