parlour 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|