///|
fn ToolingDocument::find_contract_field_definition_span(
self : ToolingDocument,
search_span : @compiler.SourceSpan,
binding : String,
field_name : String,
) -> @compiler.SourceSpan? {
match self.find_contract_type_body_span(search_span, binding) {
Some(body_span) =>
self.find_token_in_span(field_name, body_span, body_span.start)
None => self.find_field_definition_span(search_span, field_name)
}
}
///|
fn ToolingDocument::find_contract_type_body_span(
self : ToolingDocument,
search_span : @compiler.SourceSpan,
binding : String,
) -> @compiler.SourceSpan? {
match self.find_contract_type_name(search_span, binding) {
Some(type_name) =>
match self.find_substring_in_span("struct " + type_name, search_span) {
Some(start) => self.find_record_body_span(search_span, start)
None => None
}
None => None
}
}
///|
fn ToolingDocument::find_contract_type_name(
self : ToolingDocument,
search_span : @compiler.SourceSpan,
binding : String,
) -> String? {
match self.find_binding_definition_span(search_span, binding) {
Some(binding_span) => {
let chars = self.chars
let mut cursor = binding_span.end
while cursor < search_span.end &&
chars[cursor] != ':' &&
chars[cursor] != '\n' &&
chars[cursor] != '=' {
cursor += 1
}
if cursor >= search_span.end || chars[cursor] != ':' {
return None
}
cursor += 1
while cursor < search_span.end &&
(chars[cursor] == ' ' || chars[cursor] == '\t') {
cursor += 1
}
let start = cursor
while cursor < search_span.end && is_identifier_char(chars[cursor]) {
cursor += 1
}
if cursor == start {
None
} else {
Some(String::unsafe_substring(self.source, start~, end=cursor))
}
}
None => None
}
}
///|
fn ToolingDocument::find_record_body_span(
self : ToolingDocument,
search_span : @compiler.SourceSpan,
start_offset : Int,
) -> @compiler.SourceSpan? {
let chars = self.chars
let mut cursor = start_offset
while cursor < search_span.end && chars[cursor] != '{' {
cursor += 1
}
if cursor >= search_span.end {
return None
}
let body_start = cursor + 1
cursor += 1
let mut depth = 1
while cursor < search_span.end {
if chars[cursor] == '{' {
depth += 1
} else if chars[cursor] == '}' {
depth -= 1
if depth == 0 {
return Some({ start: body_start, end: cursor })
}
}
cursor += 1
}
None
}