parlour 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +1 -1
- data/lib/parlour.rb +2 -0
- data/lib/parlour/conflict_resolver.rb +38 -3
- data/lib/parlour/debugging.rb +122 -0
- data/lib/parlour/plugin.rb +1 -0
- data/lib/parlour/rbi_generator/method.rb +1 -1
- data/lib/parlour/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a670215d6246dfe4cc4aec9e3dd5121cf1da1357dbc1703a53dd059d3467d47
|
4
|
+
data.tar.gz: 6c8fa32d0adb363b72d43e307fb38c443dd469444ffbefddaa561e841b108846
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0089e4ef2b9cf1855bba3e1a8a1a5faeae2a020003c9625ef95e96fb7c6b0293cf44cf8fda4a2a312fe3ea91d9b10e05cd70d83b96cc80eb1354741958210140'
|
7
|
+
data.tar.gz: b9554148306f4a0453cf4d6e9244581a6380df6341d0ec88033b91c917ef4a1d9e67f7448cc51758b7ec8c98044583810ccb68ad5a85aa3b221086e9c105844f
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file.
|
|
3
3
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
5
5
|
|
6
|
+
## [0.8.1] - 2019-09-27
|
7
|
+
### Added
|
8
|
+
- Running with the PARLOUR_DEBUG environment variable set will now print debug
|
9
|
+
output to the console during conflict resolution.
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
- Performance is now much faster when the conflict resolver needs to resolve a
|
13
|
+
conflict between many identical objects.
|
14
|
+
|
6
15
|
## [0.8.0] - 2019-09-14
|
7
16
|
### Added
|
8
17
|
- Methods can now have type parameters specified.
|
data/README.md
CHANGED
@@ -152,7 +152,7 @@ _Have you written an awesome Parlour plugin? Please submit a PR to add it to thi
|
|
152
152
|
|
153
153
|
- [Sord](https://github.com/AaronC81/sord) - Generate RBIs from YARD documentation
|
154
154
|
- [parlour-datamapper](https://github.com/AaronC81/parlour-datamapper) - Simple plugin for generating DataMapper model types
|
155
|
-
|
155
|
+
- [sorbet-rails](https://github.com/chanzuckerberg/sorbet-rails) - Generate RBIs for Rails models, routes, mailers, etc.
|
156
156
|
|
157
157
|
## Contributing
|
158
158
|
|
data/lib/parlour.rb
CHANGED
@@ -39,23 +39,49 @@ module Parlour
|
|
39
39
|
# will be kept, or nil to keep none of them.
|
40
40
|
# @return [void]
|
41
41
|
def resolve_conflicts(namespace, &resolver)
|
42
|
+
Debugging.debug_puts(self, Debugging::Tree.begin("Resolving conflicts for #{namespace.name}..."))
|
43
|
+
|
42
44
|
# Check for multiple definitions with the same name
|
43
45
|
grouped_by_name_children = namespace.children.group_by(&:name)
|
44
46
|
|
45
47
|
grouped_by_name_children.each do |name, children|
|
48
|
+
Debugging.debug_puts(self, Debugging::Tree.begin("Checking children named #{name}..."))
|
49
|
+
|
46
50
|
if children.length > 1
|
51
|
+
Debugging.debug_puts(self, Debugging::Tree.here("Possible conflict between #{children.length} objects"))
|
52
|
+
|
47
53
|
# Special case: do we have two methods, one of which is a class method
|
48
54
|
# and the other isn't? If so, do nothing - this is fine
|
49
|
-
|
55
|
+
if children.length == 2 &&
|
50
56
|
children.all? { |c| c.is_a?(RbiGenerator::Method) } &&
|
51
57
|
children.count { |c| T.cast(c, RbiGenerator::Method).class_method } == 1
|
52
58
|
|
59
|
+
Debugging.debug_puts(self, Debugging::Tree.end("One is an instance method and one is a class method; no resolution required"))
|
60
|
+
next
|
61
|
+
end
|
62
|
+
|
53
63
|
# Special case: do we have two attributes, one of which is a class
|
54
64
|
# attribute and the other isn't? If so, do nothing - this is fine
|
55
|
-
|
65
|
+
if children.length == 2 &&
|
56
66
|
children.all? { |c| c.is_a?(RbiGenerator::Attribute) } &&
|
57
67
|
children.count { |c| T.cast(c, RbiGenerator::Attribute).class_attribute } == 1
|
58
68
|
|
69
|
+
Debugging.debug_puts(self, Debugging::Tree.end("One is an instance attribute and one is a class attribute; no resolution required"))
|
70
|
+
next
|
71
|
+
end
|
72
|
+
|
73
|
+
# Special case: are they all clearly equal? If so, remove all but one
|
74
|
+
if all_eql?(children)
|
75
|
+
Debugging.debug_puts(self, Debugging::Tree.end("All children are identical"))
|
76
|
+
|
77
|
+
# All of the children are the same, so this deletes all of them
|
78
|
+
namespace.children.delete(T.must(children.first))
|
79
|
+
|
80
|
+
# Re-add one child
|
81
|
+
namespace.children << T.must(children.first)
|
82
|
+
next
|
83
|
+
end
|
84
|
+
|
59
85
|
# We found a conflict!
|
60
86
|
# Start by removing all the conflicting items
|
61
87
|
children.each do |c|
|
@@ -66,7 +92,8 @@ module Parlour
|
|
66
92
|
# type of object, so check that first
|
67
93
|
children_type = single_type_of_array(children)
|
68
94
|
unless children_type
|
69
|
-
|
95
|
+
Debugging.debug_puts(self, Debugging::Tree.end("Children are different types; requesting manual resolution"))
|
96
|
+
# The types aren't the same, so ask the resolver what to do, and
|
70
97
|
# insert that (if not nil)
|
71
98
|
choice = resolver.call("Different kinds of definition for the same name", children)
|
72
99
|
namespace.children << choice if choice
|
@@ -77,21 +104,29 @@ module Parlour
|
|
77
104
|
first, *rest = children
|
78
105
|
first, rest = T.must(first), T.must(rest)
|
79
106
|
if T.must(first).mergeable?(T.must(rest))
|
107
|
+
Debugging.debug_puts(self, Debugging::Tree.end("Children are all mergeable; resolving automatically"))
|
80
108
|
first.merge_into_self(rest)
|
81
109
|
namespace.children << first
|
82
110
|
next
|
83
111
|
end
|
84
112
|
|
85
113
|
# I give up! Let it be resolved manually somehow
|
114
|
+
Debugging.debug_puts(self, Debugging::Tree.end("Unable to resolve automatically; requesting manual resolution"))
|
86
115
|
choice = resolver.call("Can't automatically resolve", children)
|
87
116
|
namespace.children << choice if choice
|
117
|
+
else
|
118
|
+
Debugging.debug_puts(self, Debugging::Tree.end("No conflicts"))
|
88
119
|
end
|
89
120
|
end
|
90
121
|
|
122
|
+
Debugging.debug_puts(self, Debugging::Tree.here("Resolving children..."))
|
123
|
+
|
91
124
|
# Recurse to child namespaces
|
92
125
|
namespace.children.each do |child|
|
93
126
|
resolve_conflicts(child, &resolver) if RbiGenerator::Namespace === child
|
94
127
|
end
|
128
|
+
|
129
|
+
Debugging.debug_puts(self, Debugging::Tree.end("All children done"))
|
95
130
|
end
|
96
131
|
|
97
132
|
private
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# typed: true
|
2
|
+
require 'rainbow'
|
3
|
+
|
4
|
+
module Parlour
|
5
|
+
# Contains methods to enable debugging facilities for Parlour.
|
6
|
+
module Debugging
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
@debug_mode = !ENV["PARLOUR_DEBUG"].nil?
|
10
|
+
|
11
|
+
# Set whether debug messages should be printed.
|
12
|
+
# @param [Boolean] value True if debug messages will be printed, false
|
13
|
+
# otherwise.
|
14
|
+
# @return [Boolean] The new value.
|
15
|
+
sig { params(value: T::Boolean).returns(T::Boolean) }
|
16
|
+
def self.debug_mode=(value)
|
17
|
+
@debug_mode = value
|
18
|
+
end
|
19
|
+
|
20
|
+
# Whether debug messages sent by {#debug_puts} should be printed.
|
21
|
+
# Defaults to true if the PARLOUR_DEBUG environment variable is set.
|
22
|
+
# @return [Boolean] True if debug messages will be printed, false otherwise.
|
23
|
+
sig { returns(T::Boolean) }
|
24
|
+
def self.debug_mode?
|
25
|
+
@debug_mode
|
26
|
+
end
|
27
|
+
|
28
|
+
# Prints a message with a debugging prefix to STDOUT if {#debug_mode?} is
|
29
|
+
# true.
|
30
|
+
# @params [Object] object The object which is printing this debug message.
|
31
|
+
# Callers should pass +self+.
|
32
|
+
# @params [String] message The message to print. It should not contain
|
33
|
+
# newlines.
|
34
|
+
# @return [void]
|
35
|
+
sig { params(object: T.untyped, message: String).void }
|
36
|
+
def self.debug_puts(object, message)
|
37
|
+
return unless debug_mode?
|
38
|
+
name = Rainbow("#{name_for_debug_caller(object)}: ").magenta.bright.bold
|
39
|
+
prefix = Rainbow("Parlour debug: ").blue.bright.bold
|
40
|
+
puts prefix + name + message
|
41
|
+
end
|
42
|
+
|
43
|
+
# Converts the given object into a human-readable prefix to a debug message.
|
44
|
+
# For example, passing an instance of {ConflictResolver} returns
|
45
|
+
# "conflict resolver". If the object type is unknown, this returns its class
|
46
|
+
# name.
|
47
|
+
# @param [Object] object The object to convert.
|
48
|
+
# @return [String] A string describing the object for {#debug_puts}.
|
49
|
+
sig { params(object: T.untyped).returns(String) }
|
50
|
+
def self.name_for_debug_caller(object)
|
51
|
+
case object
|
52
|
+
when ConflictResolver
|
53
|
+
"conflict resolver"
|
54
|
+
when RbiGenerator
|
55
|
+
"RBI generator"
|
56
|
+
else
|
57
|
+
if ((object < Plugin) rescue false)
|
58
|
+
return "plugin #{object.name}"
|
59
|
+
end
|
60
|
+
object.class.name
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# A module for generating a globally-consistent, nicely-formatted tree of
|
65
|
+
# output using Unicode block characters.
|
66
|
+
module Tree
|
67
|
+
extend T::Sig
|
68
|
+
|
69
|
+
# The number of spaces to indent each layer of the tree by. Should be at
|
70
|
+
# least 1.
|
71
|
+
INDENT_SPACES = 2
|
72
|
+
|
73
|
+
# The current indent level of the tree.
|
74
|
+
@indent_level = 0
|
75
|
+
|
76
|
+
# Returns a new heading, and then decents the tree one level into it.
|
77
|
+
# (That is, future output will go under the new heading.)
|
78
|
+
# @param [String] message The heading.
|
79
|
+
# @return [String] The line of this tree which should be printed.
|
80
|
+
sig { params(message: String).returns(String) }
|
81
|
+
def self.begin(message)
|
82
|
+
result = line_prefix + '├' + text_prefix + Rainbow(message).green.bright.bold
|
83
|
+
@indent_level += 1
|
84
|
+
result
|
85
|
+
end
|
86
|
+
|
87
|
+
# Prints a new tree element at the current level.
|
88
|
+
# @param [String] message The element.
|
89
|
+
# @return [String] The line of this tree which should be printed.
|
90
|
+
sig { params(message: String).returns(String) }
|
91
|
+
def self.here(message)
|
92
|
+
line_prefix + '├' + text_prefix + message
|
93
|
+
end
|
94
|
+
|
95
|
+
# Prints the final tree element at the current level, then ascends one
|
96
|
+
# level.
|
97
|
+
# @param [String] message The element.
|
98
|
+
# @return [String] The line of this tree which should be printed.
|
99
|
+
sig { params(message: String).returns(String) }
|
100
|
+
def self.end(message)
|
101
|
+
result = line_prefix + '└' + text_prefix + message
|
102
|
+
@indent_level = [0, @indent_level - 1].max
|
103
|
+
result
|
104
|
+
end
|
105
|
+
|
106
|
+
# The prefix which should be printed before anything else on this line of
|
107
|
+
# the tree, based on the current indent level.
|
108
|
+
# @return [String]
|
109
|
+
def self.line_prefix
|
110
|
+
@indent_level.times.map { '│' + ' ' * INDENT_SPACES }.join
|
111
|
+
end
|
112
|
+
|
113
|
+
# The horizontal lines which should be printed between the beginning of
|
114
|
+
# the current element and its text, based on the specified number of
|
115
|
+
# spaces to use for indents.
|
116
|
+
# @return [String]
|
117
|
+
def self.text_prefix
|
118
|
+
'─' * (INDENT_SPACES - 1) + " "
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/lib/parlour/plugin.rb
CHANGED
@@ -54,7 +54,7 @@ module Parlour
|
|
54
54
|
yield_self(&block) if block
|
55
55
|
end
|
56
56
|
|
57
|
-
sig { overridable.params(other: Object).returns(T::Boolean) }
|
57
|
+
sig { overridable.params(other: Object).returns(T::Boolean).checked(:never) }
|
58
58
|
# Returns true if this instance is equal to another method.
|
59
59
|
#
|
60
60
|
# @param other [Object] The other instance. If this is not a {Method} (or a
|
data/lib/parlour/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parlour
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Christiansen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sorbet-runtime
|
@@ -130,6 +130,7 @@ files:
|
|
130
130
|
- exe/parlour
|
131
131
|
- lib/parlour.rb
|
132
132
|
- lib/parlour/conflict_resolver.rb
|
133
|
+
- lib/parlour/debugging.rb
|
133
134
|
- lib/parlour/kernel_hack.rb
|
134
135
|
- lib/parlour/plugin.rb
|
135
136
|
- lib/parlour/rbi_generator.rb
|