orbacle 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile +2 -0
  7. data/Gemfile.lock +119 -0
  8. data/LICENSE +22 -0
  9. data/Makefile +57 -0
  10. data/README.md +53 -0
  11. data/circle.yml +82 -0
  12. data/exe/orbaclerun +6 -0
  13. data/index.html +106 -0
  14. data/lib/orbacle.rb +96 -0
  15. data/lib/orbacle/ast_utils.rb +35 -0
  16. data/lib/orbacle/bottom_type.rb +23 -0
  17. data/lib/orbacle/builder.rb +1414 -0
  18. data/lib/orbacle/builder/context.rb +71 -0
  19. data/lib/orbacle/builder/operator_assignment_processors.rb +80 -0
  20. data/lib/orbacle/class_type.rb +32 -0
  21. data/lib/orbacle/command_line_interface.rb +107 -0
  22. data/lib/orbacle/const_name.rb +33 -0
  23. data/lib/orbacle/const_ref.rb +53 -0
  24. data/lib/orbacle/constants_tree.rb +73 -0
  25. data/lib/orbacle/define_builtins.rb +139 -0
  26. data/lib/orbacle/engine.rb +74 -0
  27. data/lib/orbacle/find_definition_under_position.rb +76 -0
  28. data/lib/orbacle/generic_type.rb +35 -0
  29. data/lib/orbacle/global_tree.rb +280 -0
  30. data/lib/orbacle/graph.rb +126 -0
  31. data/lib/orbacle/indexer.rb +151 -0
  32. data/lib/orbacle/integer_id_generator.rb +13 -0
  33. data/lib/orbacle/lambda_type.rb +37 -0
  34. data/lib/orbacle/lang_server.rb +64 -0
  35. data/lib/orbacle/main_type.rb +23 -0
  36. data/lib/orbacle/nesting.rb +78 -0
  37. data/lib/orbacle/node.rb +23 -0
  38. data/lib/orbacle/nominal_type.rb +32 -0
  39. data/lib/orbacle/ruby_parser.rb +19 -0
  40. data/lib/orbacle/scope.rb +63 -0
  41. data/lib/orbacle/selfie.rb +41 -0
  42. data/lib/orbacle/type_pretty_printer.rb +24 -0
  43. data/lib/orbacle/typing_service.rb +816 -0
  44. data/lib/orbacle/union_type.rb +40 -0
  45. data/lib/orbacle/uuid_id_generator.rb +11 -0
  46. data/lib/orbacle/worklist.rb +51 -0
  47. data/orbacle.gemspec +33 -0
  48. metadata +258 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b560995e47155365bd986cb4ef871acf85fb7cb4753c098f7f7f60bf86cb0a30
4
+ data.tar.gz: 37ce9c0971c5b2afeee80687daf0cb1aede67e82bc43dfd207223244c1398d0b
5
+ SHA512:
6
+ metadata.gz: 546a7ca50aa3c04276a13a934e41cda17836fa795d33391c6d3420e0b4764d0a643940c141a58277e9e41f5b4ddebbd2deb4b0c6a10ff61931621e565012aed3
7
+ data.tar.gz: d9834d7895f9ce459516104d3011fa88e4b06d8fb5178fc13dfcd776fd731692ad505d3e91886399a71387beafc3c6af6ceb300ee3fe62d2a1bac64655683209
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.db
2
+ *.gem
3
+ data.js
4
+ tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.5.1
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+
2
+ ## 0.1.0
3
+
4
+ * First public version released
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,119 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ orbacle (0.1.0)
5
+ lsp-protocol (>= 0.0.3)
6
+ parser (~> 2.4.0.2)
7
+ priority_queue_cxx
8
+ rgl (~> 0.5.3)
9
+ rubytree (~> 0.9.7)
10
+
11
+ GEM
12
+ remote: https://rubygems.org/
13
+ specs:
14
+ abstract_type (0.0.7)
15
+ adamantium (0.2.0)
16
+ ice_nine (~> 0.11.0)
17
+ memoizable (~> 0.4.0)
18
+ anima (0.3.0)
19
+ abstract_type (~> 0.0.7)
20
+ adamantium (~> 0.2)
21
+ equalizer (~> 0.0.11)
22
+ ast (2.4.0)
23
+ byebug (10.0.2)
24
+ concord (0.1.5)
25
+ adamantium (~> 0.2.0)
26
+ equalizer (~> 0.0.9)
27
+ diff-lcs (1.3)
28
+ equalizer (0.0.11)
29
+ hash_diff (0.6.3)
30
+ ice_nine (0.11.2)
31
+ json (1.8.6)
32
+ lazy_priority_queue (0.1.1)
33
+ lsp-protocol (0.0.3)
34
+ memoizable (0.4.2)
35
+ thread_safe (~> 0.3, >= 0.3.1)
36
+ mini_portile2 (2.3.0)
37
+ morpher (0.2.6)
38
+ abstract_type (~> 0.0.7)
39
+ adamantium (~> 0.2.0)
40
+ anima (~> 0.3.0)
41
+ ast (~> 2.2)
42
+ concord (~> 0.1.5)
43
+ equalizer (~> 0.0.9)
44
+ ice_nine (~> 0.11.0)
45
+ procto (~> 0.0.2)
46
+ mutant (0.8.14)
47
+ abstract_type (~> 0.0.7)
48
+ adamantium (~> 0.2.0)
49
+ anima (~> 0.3.0)
50
+ ast (~> 2.2)
51
+ concord (~> 0.1.5)
52
+ diff-lcs (~> 1.3)
53
+ equalizer (~> 0.0.9)
54
+ ice_nine (~> 0.11.1)
55
+ memoizable (~> 0.4.2)
56
+ morpher (~> 0.2.6)
57
+ parallel (~> 1.3)
58
+ parser (>= 2.3.1.4, < 2.5)
59
+ procto (~> 0.0.2)
60
+ regexp_parser (~> 0.4.3)
61
+ unparser (~> 0.2.5)
62
+ mutant-rspec (0.8.14)
63
+ mutant (~> 0.8.14)
64
+ rspec-core (>= 3.4.0, < 3.7.0)
65
+ nokogiri (1.8.4)
66
+ mini_portile2 (~> 2.3.0)
67
+ parallel (1.12.1)
68
+ parser (2.4.0.2)
69
+ ast (~> 2.3)
70
+ priority_queue_cxx (0.3.4)
71
+ procto (0.0.3)
72
+ regexp_parser (0.4.13)
73
+ rgl (0.5.3)
74
+ lazy_priority_queue (~> 0.1.0)
75
+ stream (~> 0.5.0)
76
+ rspec (3.6.0)
77
+ rspec-core (~> 3.6.0)
78
+ rspec-expectations (~> 3.6.0)
79
+ rspec-mocks (~> 3.6.0)
80
+ rspec-core (3.6.0)
81
+ rspec-support (~> 3.6.0)
82
+ rspec-expectations (3.6.0)
83
+ diff-lcs (>= 1.2.0, < 2.0)
84
+ rspec-support (~> 3.6.0)
85
+ rspec-mocks (3.6.0)
86
+ diff-lcs (>= 1.2.0, < 2.0)
87
+ rspec-support (~> 3.6.0)
88
+ rspec-support (3.6.0)
89
+ ruby-prof (0.17.0)
90
+ rubytree (0.9.7)
91
+ json (~> 1.8)
92
+ structured_warnings (~> 0.2)
93
+ stream (0.5)
94
+ structured_warnings (0.3.0)
95
+ thread_safe (0.3.6)
96
+ unparser (0.2.7)
97
+ abstract_type (~> 0.0.7)
98
+ adamantium (~> 0.2.0)
99
+ concord (~> 0.1.5)
100
+ diff-lcs (~> 1.3)
101
+ equalizer (~> 0.0.9)
102
+ parser (>= 2.3.1.2, < 2.6)
103
+ procto (~> 0.0.2)
104
+
105
+ PLATFORMS
106
+ ruby
107
+
108
+ DEPENDENCIES
109
+ bundler (~> 1.9)
110
+ byebug
111
+ hash_diff (~> 0.6.2)
112
+ mutant-rspec
113
+ nokogiri (>= 1.8.4)
114
+ orbacle!
115
+ rspec
116
+ ruby-prof
117
+
118
+ BUNDLED WITH
119
+ 1.16.2
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Rafał Łasocha
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/Makefile ADDED
@@ -0,0 +1,57 @@
1
+ mutant:
2
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::Builder#handle_int"
3
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::Builder#handle_float"
4
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::Builder#handle_rational"
5
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::Builder#handle_complex"
6
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::Builder#handle_bool"
7
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::DefineBuiltins"
8
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::RubyParser"
9
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::ConstantsTree"
10
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::FindDefinitionUnderPosition"
11
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::LangServer"
12
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::Engine"
13
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#add_lambda"
14
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#get_lambda"
15
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#get_instance_methods_from_class_id"
16
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#find_instance_method_from_class_id"
17
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#get_instance_methods_from_class_name"
18
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#find_instance_method_from_class_name"
19
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#get_class_methods_from_class_name"
20
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#find_class_method_from_class_name"
21
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#find_super_method"
22
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#change_method_visibility"
23
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#get_class"
24
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#add_klass"
25
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#add_mod"
26
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#get_module"
27
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#get_definition"
28
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#get_parent_of"
29
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#set_type_of"
30
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#type_of"
31
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#get_eigenclass_of_definition"
32
+ @MUTANT_TESTING=true bundle exec mutant --include lib --require orbacle --use rspec "Orbacle::GlobalTree#get_methods"
33
+
34
+ test: test-unit test-performance
35
+
36
+ test-unit:
37
+ bundle exec rspec --tag "~performance" spec
38
+
39
+ test-performance:
40
+ bundle exec rspec --tag performance spec
41
+
42
+ refresh-stats:
43
+ bundle exec ruby script/fetch_most_popular_rubygems_list.rb
44
+
45
+ bundle:
46
+ bundle install
47
+
48
+ index-itself:
49
+ bundle exec exe/orbaclerun index
50
+
51
+ setup: bundle
52
+
53
+ build:
54
+ @gem build orbacle.gemspec
55
+
56
+ install: build
57
+ @gem install orbacle-0.0.1.gem
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ [![CircleCI](https://circleci.com/gh/swistak35/orbacle/tree/master.svg?style=svg)](https://circleci.com/gh/swistak35/orbacle/tree/master)
2
+
3
+ # Orbacle
4
+
5
+ <img src="http://swistak35.com/img/orbacle-logo.png" alt="Orbacle logo" width="100px" align="left" />
6
+
7
+ Language server using engine allowing for smart jump-to-definitions, understanding metaprogramming definitions, refactoring and more.
8
+
9
+ Doing as MSc thesis for [Institute of Computer Science, University of Wrocław](http://ii.uni.wroc.pl).
10
+
11
+ ## Objectives
12
+
13
+ Create a language server for ruby, which can be used across different code editors, like Vim, Emacs or Atom. Focus on understanding of the code in order to provide best functionalities of "go-to definition", autocompletion and refactorings. The idea is to infer information about variables (i.e. their "types"), **without requiring developer to write any annotations**, just like IDEs do that - through static analysis.
14
+
15
+ ## Current status
16
+
17
+ Currently language server supports:
18
+ * hover request - information about "type" of an expression
19
+ * jump to definition - jump to definition of constant or method
20
+
21
+ ## Setup
22
+
23
+ ### Prerequisite indexing
24
+
25
+ 1. Install `orbacle` gem.
26
+ 2. Run `orbaclerun -d <your_project_directory> index`
27
+
28
+ It will show you how long does it take to index your project, i.e. how long do you have to wait after editor start to have language server functional underneath.
29
+
30
+ ### Vim
31
+
32
+ Using `vim-plug`:
33
+
34
+ ```
35
+ Plug 'autozimu/LanguageClient-neovim', { 'branch': 'next', 'do': 'bash install.sh' }
36
+
37
+ let g:LanguageClient_serverCommands = {
38
+ \ 'ruby': ['orbaclerun', 'file-server'],
39
+ \ }
40
+ nnoremap <localleader>lj :call LanguageClient_textDocument_definition()<CR>
41
+ nnoremap T :call LanguageClient_textDocument_hover()<CR>
42
+ " timeout has to be bigger than time needed to index your project
43
+ let g:LanguageClient_waitOutputTimeout = 240
44
+ ```
45
+
46
+ ## Contributing
47
+
48
+ Currently I do not accept contributions, as this is part of MSc thesis. However features ideas and bug reports are accepted.
49
+
50
+ ## Bibliography
51
+
52
+ * [Tern](http://marijnhaverbeke.nl/blog/tern.html)
53
+ * Fast Interprocedural Class Analysis, Greg DeFouw, David Grove, Craig Chambers, July 1997
data/circle.yml ADDED
@@ -0,0 +1,82 @@
1
+ version: 2
2
+ jobs:
3
+ build-2.3.7:
4
+ docker:
5
+ - image: circleci/ruby:2.3.7
6
+ environment:
7
+ BUNDLE_JOBS: 3
8
+ BUNDLE_RETRY: 3
9
+ BUNDLE_PATH: ~/vendor/bundle
10
+ steps:
11
+ - checkout
12
+ - restore_cache:
13
+ key: bundle-v2-{{ checksum "Gemfile.lock" }}
14
+ - run: make bundle
15
+ - save_cache:
16
+ key: bundle-v2-{{ checksum "Gemfile.lock" }}
17
+ paths:
18
+ - ~/vendor/bundle
19
+ - run: make test
20
+ - run: make index-itself
21
+ build-2.4.4:
22
+ docker:
23
+ - image: circleci/ruby:2.4.4
24
+ environment:
25
+ BUNDLE_JOBS: 3
26
+ BUNDLE_RETRY: 3
27
+ BUNDLE_PATH: ~/vendor/bundle
28
+ steps:
29
+ - checkout
30
+ - restore_cache:
31
+ key: bundle-v2-{{ checksum "Gemfile.lock" }}
32
+ - run: make bundle
33
+ - save_cache:
34
+ key: bundle-v2-{{ checksum "Gemfile.lock" }}
35
+ paths:
36
+ - ~/vendor/bundle
37
+ - run: make test
38
+ - run: make index-itself
39
+ build-2.5.1:
40
+ docker:
41
+ - image: circleci/ruby:2.5.1
42
+ environment:
43
+ BUNDLE_JOBS: 3
44
+ BUNDLE_RETRY: 3
45
+ BUNDLE_PATH: ~/vendor/bundle
46
+ steps:
47
+ - checkout
48
+ - restore_cache:
49
+ key: bundle-v2-{{ checksum "Gemfile.lock" }}
50
+ - run: make bundle
51
+ - save_cache:
52
+ key: bundle-v2-{{ checksum "Gemfile.lock" }}
53
+ paths:
54
+ - ~/vendor/bundle
55
+ - run: make test
56
+ - run: make index-itself
57
+ mutant:
58
+ docker:
59
+ - image: circleci/ruby:2.5.1
60
+ environment:
61
+ BUNDLE_JOBS: 3
62
+ BUNDLE_RETRY: 3
63
+ BUNDLE_PATH: ~/vendor/bundle
64
+ steps:
65
+ - checkout
66
+ - restore_cache:
67
+ key: bundle-v2-{{ checksum "Gemfile.lock" }}
68
+ - run: make bundle
69
+ - save_cache:
70
+ key: bundle-v2-{{ checksum "Gemfile.lock" }}
71
+ paths:
72
+ - ~/vendor/bundle
73
+ - run: make mutant
74
+
75
+ workflows:
76
+ version: 2
77
+ main:
78
+ jobs:
79
+ - build-2.3.7
80
+ - build-2.4.4
81
+ - build-2.5.1
82
+ - mutant
data/exe/orbaclerun ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'orbacle'
4
+
5
+ cli = Orbacle::CommandLineInterface.new
6
+ cli.(ARGV)
data/index.html ADDED
@@ -0,0 +1,106 @@
1
+ <html>
2
+ <head>
3
+ <script type="text/javascript" src="http://localhost:5000/data.js"></script>
4
+ <script>
5
+ function showFile(uri) {
6
+ found_element = window.orbacleFiles.find(function(elem) { return (elem[0] == uri) })
7
+ filetext = atob(found_element[1]);
8
+ window.currentRawText = filetext;
9
+ code = document.getElementById('code')
10
+ code.innerHTML = window.currentRawText
11
+
12
+ const nodelist = document.getElementById('nodelist');
13
+ const nodesForFile = orbacleNodes.filter(function(node) { return (node[2] == uri)});
14
+ nodelist.innerHTML = nodesForFile.map(function(node) { return (`<tr onclick='highlight(${node[3]}, ${node[4]}, ${node[5]}, ${node[6]}, "${node[1]}")'><td>${node[3]}:${node[4]} - ${node[5]}:${node[6]}</td><td>${node[0]}</td><td>${node[1]}</td></tr>`)}).join("\n");
15
+ }
16
+
17
+ function highlight(startLine, startCharacter, endLine, endCharacter, type) {
18
+ oldLines = window.currentRawText.split("\n")
19
+ code = document.getElementById('code')
20
+ if (startLine == endLine) {
21
+ startLineContent = oldLines[startLine];
22
+ newStartLineContent = startLineContent.substr(0, startCharacter) + '<b>' + startLineContent.substr(startCharacter, endCharacter - startCharacter + 1) + '</b>' + startLineContent.substr(endCharacter + 1);
23
+ oldLines[startLine] = newStartLineContent;
24
+ } else {
25
+ startLineContent = oldLines[startLine];
26
+ newStartLineContent = startLineContent.substr(0, startCharacter) + '<b>' + startLineContent.substr(startCharacter);
27
+ oldLines[startLine] = newStartLineContent;
28
+
29
+ endLineContent = oldLines[endLine];
30
+ newEndLineContent = endLineContent.substr(0, endCharacter + 1) + '</b>' + endLineContent.substr(endCharacter + 1);
31
+ oldLines[endLine] = newEndLineContent;
32
+ }
33
+ code.innerHTML = oldLines.join("\n");
34
+
35
+ const typeNode = document.getElementById('type')
36
+ typeNode.innerHTML = `Type of selected element: <b>${type}<b>`;
37
+ }
38
+
39
+ window.onload = function(e){
40
+ const filesList = document.getElementById('fileslist');
41
+ const filePaths = orbacleFiles.map(function(file) { return file[0]; });
42
+ filesList.innerHTML = filePaths.map(function(file) { return (`<a href='#' onclick='showFile("${file}");'>${file}</a>`) }).join(" | ");
43
+ }
44
+ </script>
45
+ <style>
46
+ #code b {
47
+ background-color: red;
48
+ }
49
+
50
+ #files, #left, #type, #code, #nodes {
51
+ border: black 1px solid;
52
+ display: block;
53
+ }
54
+
55
+ #files {
56
+ width: 100%;
57
+ }
58
+
59
+ #left {
60
+ float: left;
61
+ width: 700px;
62
+ }
63
+
64
+ #type {
65
+ float: left;
66
+ width: 100%;
67
+ height: 50px;
68
+ text-align: center;
69
+ }
70
+
71
+ #code {
72
+ float: left;
73
+ width: 100%;
74
+ font-family: "Courier New", Courier, monospace;
75
+ white-space: pre-wrap;
76
+ max-height: 700px;
77
+ overflow-y: scroll;
78
+ }
79
+
80
+ #nodes {
81
+ width: 700px;
82
+ float: left;
83
+ max-height: 700px;
84
+ overflow-y: scroll;
85
+ }
86
+
87
+ </style>
88
+ </head>
89
+ <body>
90
+ <div id="files">
91
+ <ul id="fileslist">
92
+ <li><a onclick="showFile('data_flow_graph.rb')">data_flow_graph.rb</a></li>
93
+ </ul>
94
+ </div>
95
+ <div id="left">
96
+ <div id="type">Unknown</div>
97
+ <div id="code">
98
+ Load some file on the left
99
+ </div>
100
+ </div>
101
+ <div id="nodes">
102
+ <table id="nodelist">
103
+ </table>
104
+ </div>
105
+ </body>
106
+ </html>