Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflow/ci.yml → .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ jobs:
fail-fast: false
matrix:
ruby:
- '3.0'
- '3.1'
- '3.2'
- '3.3'
- '3.4'
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/gem-push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Ruby Gem

on:
release:
types: [ published ]

jobs:
build:
name: Build + Publish
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- uses: aha-app/checkout@v4
- name: Set up Ruby
uses: aha-app/setup-ruby@v1
with:
ruby-version: 3.4

- name: Publish to RubyGems
run: |
mkdir -p $HOME/.gem
touch $HOME/.gem/credentials
chmod 0600 $HOME/.gem/credentials
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
gem build *.gemspec
gem push *.gem
env:
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
44 changes: 44 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
AllCops:
Exclude:
- '*.gemspec'
NewCops: enable
SuggestExtensions: false

Gemspec:
Enabled: false

Metrics/ClassLength:
Enabled: false

Metrics/AbcSize:
Enabled: false

Metrics/CyclomaticComplexity:
Enabled: false

Metrics/MethodLength:
Enabled: false

Metrics/PerceivedComplexity:
Enabled: false

Layout/LineLength:
Enabled: false

Metrics/BlockNesting:
Enabled: false

Metrics/BlockLength:
Enabled: false

Style/StringConcatenation:
Enabled: false

Style/StringLiterals:
Enabled: false

Style/NumericLiterals:
Enabled: false

Style/IfUnlessModifier:
Enabled: false
23 changes: 11 additions & 12 deletions lib/json_completer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def complete(partial_json)
end

return input if input.empty?
return input if is_valid_json_primitive_or_document?(input)
return input if valid_json_primitive_or_document?(input)

# If input hasn't grown since last time, just return completed version of existing state
if @state.input_length == input.length && [email protected]_tokens.empty?
Expand All @@ -73,15 +73,15 @@ def complete(partial_json)
incomplete_string_buffer = @state.incomplete_string_buffer || StringIO.new('"')
incomplete_string_escape_state = @state.incomplete_string_escape_state
# Remove the auto-completed string from output_tokens since we'll add the real one
output_tokens.pop if output_tokens.last&.start_with?('"') && output_tokens.last&.end_with?('"')
output_tokens.pop if output_tokens.last&.start_with?('"') && output_tokens.last.end_with?('"')
end

# Process from the current index
while index < length
# Special case: continuing an incomplete string
if incomplete_string_buffer && index == @state.last_index
str_value, new_index, terminated, new_buffer, new_escape_state = continue_parsing_string(
input, incomplete_string_start, incomplete_string_buffer, incomplete_string_escape_state
input, incomplete_string_buffer, incomplete_string_escape_state
)
if terminated
output_tokens << str_value
Expand Down Expand Up @@ -227,9 +227,7 @@ def finalize_completion(output_tokens, context_stack, incomplete_string_buffer =

# If odd number of trailing backslashes, remove the last one (incomplete escape)
# If even number, they're all paired as escaped backslashes, don't remove any
if trailing_backslashes.odd?
buffer_str = buffer_str[0...-1]
end
buffer_str = buffer_str[0...-1] if trailing_backslashes.odd?

# Check for incomplete unicode escape after handling backslashes
if buffer_str =~ /\\u[0-9a-fA-F]{0,3}\z/ # Incomplete unicode
Expand Down Expand Up @@ -353,7 +351,7 @@ def parse_string_with_state(input, index)

# Continues parsing an incomplete string from saved state
# Returns [string_value, new_index, was_terminated, buffer, escape_state]
def continue_parsing_string(input, string_start_index, buffer, escape_state)
def continue_parsing_string(input, buffer, escape_state)
# Buffer should not have closing quote - we removed it from parse_string_with_state

index = @state.last_index
Expand Down Expand Up @@ -589,7 +587,8 @@ def parse_number(input, index)
else
(temp_num_val.include?('.') ? temp_num_val + '0' : temp_num_val)
end,
index - start_index]
index - start_index
]
end

num_str << input[index] # 'e' or 'E'
Expand Down Expand Up @@ -631,7 +630,7 @@ def consume_and_complete_keyword(input, index, target_keyword)
# Mismatch
end
# If at least the first char matched, we complete to the target_keyword
return [target_keyword, consumed_count] if consumed_count > 0
return [target_keyword, consumed_count] if consumed_count.positive?

# Fallback (should not be reached if called correctly, i.e., input[index] is t,f, or n)
# This indicates the char was not the start of the expected keyword.
Expand Down Expand Up @@ -702,21 +701,21 @@ def remove_trailing_comma(output_tokens)

output_tokens.slice!(last_token_idx)
# Also remove any whitespace tokens that were before this comma and are now effectively trailing
while last_token_idx > 0 && output_tokens[last_token_idx - 1].strip.empty?
while last_token_idx.positive? && output_tokens[last_token_idx - 1].strip.empty?
output_tokens.slice!(last_token_idx - 1)
last_token_idx -= 1
end
end

# Checks if a string is a valid JSON primitive or a complete JSON document.
# This is a helper for early exit if input is already fine.
def is_valid_json_primitive_or_document?(str)
def valid_json_primitive_or_document?(str)
# Check for simple primitives first
return true if VALID_PRIMITIVES.include?(str)
# Check for valid number (simplified regex, full JSON number is complex)
# Allows integers, floats, but not ending with '.' or 'e'/'E' without digits
if str.match?(/\A-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?\z/) &&
!str.end_with?('.') && !str.match?(/[eE][+-]?$/)
!str.end_with?('.') && !str.match?(/[eE][+-]?$/)
return true
end
# Check for valid string literal
Expand Down
Loading