Permalink
Browse files

add link to function source

hardcoded to elixir github repo for now
  • Loading branch information...
1 parent 174ea7c commit b754ffac8082a3e30e2ce8b3cc82200e22b6a14c @lest committed Apr 27, 2012
Showing with 38 additions and 15 deletions.
  1. +1 −1 lib/exdoc.ex
  2. +7 −6 lib/exdoc/html_formatter.ex
  3. +10 −1 lib/exdoc/retriever.ex
  4. +6 −1 test/exdoc/html_formatter_test.exs
  5. +14 −6 test/exdoc/retriever_test.exs
View
@@ -67,7 +67,7 @@ defmodule ExDoc do
Erlang.file.write_file("#{output_path}/index.html", content)
end
- defp get_names({ module_name, { _, functions }}) do
+ defp get_names({ module_name, _, { _, functions }}) do
functions = Enum.map functions, get_function_name(&1)
{ module_name, functions }
end
@@ -1,6 +1,6 @@
defmodule ExDoc.HTMLFormatter do
- def format_docs({name,{ moduledoc, docs }}, output_path) do
- docs = generate_html_for_docs(docs)
+ def format_docs({name, source_path, { moduledoc, docs }}, output_path) do
+ docs = generate_html_for_docs(source_path, docs)
moduledoc = generate_html_for_moduledoc(moduledoc)
function_docs = Enum.filter_map docs, fn(x, do: filter_by_type(x, :def)), fn(x, do: get_content(x))
macro_docs = Enum.filter_map docs, fn(x, do: filter_by_type(x, :defmacro)), fn(x, do: get_content(x))
@@ -33,15 +33,16 @@ defmodule ExDoc.HTMLFormatter do
Markdown.to_html(doc)
end
- defp generate_html_for_docs(docs) do
- Enum.map docs, extract_docs(&1)
+ defp generate_html_for_docs(source_path, docs) do
+ Enum.map docs, extract_docs(source_path, &1)
end
- defp extract_docs({ { name, arity }, _line, type, doc }) do
+ defp extract_docs(source_path, { { name, arity }, line, type, doc }) do
html = if doc, do: Markdown.to_html(doc), else: ""
function_name = "#{name}/#{arity}"
- content = %b{<div class="function"><div class="function-title" id="#{function_name}">\n<b>#{function_name}</b>\n</div>\n<div class="description">\n#{html}</div>\n</div>\n}
+ source_link = %b{<a href="https://github.com/elixir-lang/elixir/blob/master/#{source_path}#L#{line}" target="_blank">Source</a>}
+ content = %b{<div class="function"><div class="function-title" id="#{function_name}">\n<b>#{function_name}</b>\n</div>\n<div class="description">\n#{html}</div>\n#{source_link}</div>\n}
{ type, content }
end
View
@@ -12,7 +12,7 @@ defmodule ExDoc.Retriever do
moduledoc = module.__info__(:moduledoc)
docs = Enum.filter module.__info__(:docs), has_doc?(&1)
- { module_name, { moduledoc, docs } }
+ { module_name, source_path(module), { moduledoc, docs } }
end
defp has_doc?({_, _, _, false}) do
@@ -33,4 +33,13 @@ defmodule ExDoc.Retriever do
hierarchy = :lists.subtract name, relative
Enum.join hierarchy, "."
end
+
+ defp source_path(module) do
+ compile_info = module.__info__(:compile)
+ compile_options = :proplists.get_value :options, compile_info
+ compile_source = :proplists.get_value :source, compile_info
+
+ list_to_binary :lists.nthtail(length(compile_source) + 1,
+ :proplists.get_value(:source, compile_options))
+ end
end
@@ -15,8 +15,12 @@ defmodule ExDoc.HTMLFormatterTest do
File.expand_path "test/tmp/output"
end
+ defp source_root_url do
+ "https://github.com/elixir-lang/elixir/blob/master/"
+ end
+
test "format_docs generate only the module name when there's no more info" do
- ExDoc.HTMLFormatter.format_docs({"XPTOModule", {{1, nil}, []}}, output_dir)
+ ExDoc.HTMLFormatter.format_docs({"XPTOModule", "", {{1, nil}, []}}, output_dir)
content = File.read!("#{output_dir}/XPTOModule.html")
assert Regex.match?(%r/<title>XPTOModule<\/title>/, content)
@@ -39,5 +43,6 @@ defmodule ExDoc.HTMLFormatterTest do
assert Regex.match?(%r/example\/0.*Some example/m, content)
assert Regex.match?(%r/example_without_docs\/0.*<div class="description">.*<\/div>/m, content)
assert Regex.match?(%r/example_1\/0.*Another example/m, content)
+ assert Regex.match?(%r{<a href="#{source_root_url}test/fixtures/compiled_with_docs.ex#L10"[^>]*>Source<\/a>}m, content)
end
end
@@ -12,35 +12,35 @@ defmodule ExDoc.RetrieverTest do
test "get_docs returns the module name" do
file = "#{input_path}/__MAIN__/CompiledWithDocs.beam"
- assert_match [{ "CompiledWithDocs", _ }], R.get_docs([file], input_path)
+ assert_match [{ "CompiledWithDocs", _, _ }], R.get_docs([file], input_path)
end
test "get_docs returns the nested module name" do
file = "#{input_path}/__MAIN__/ExDocTest/Nested.beam"
- assert_match [{ "ExDocTest.Nested", _ }], R.get_docs([file], input_path)
+ assert_match [{ "ExDocTest.Nested", _, _ }], R.get_docs([file], input_path)
end
test "get_docs returns the moduledoc info" do
file = "#{input_path}/__MAIN__/CompiledWithDocs.beam"
- [{ _, {moduledoc, _} }] = R.get_docs([file], input_path)
+ [{ _, _, {moduledoc, _} }] = R.get_docs([file], input_path)
assert_match { 1, "moduledoc\n\n\#\# Example\n CompiledWithDocs.example\n" }, moduledoc
end
test "get_docs returns nil if there's no moduledoc info" do
file = "#{input_path}/__MAIN__/CompiledWithoutDocs.beam"
- [{ _, {moduledoc, _} }] = R.get_docs([file], input_path)
+ [{ _, _, {moduledoc, _} }] = R.get_docs([file], input_path)
assert_match { _, nil }, moduledoc
end
test "get_docs returns the doc info for each module function" do
file = "#{input_path}/__MAIN__/CompiledWithDocs.beam"
- [{ _, {_, doc} }] = R.get_docs([file], input_path)
+ [{ _, _, {_, doc} }] = R.get_docs([file], input_path)
assert_match [
{{:example, 0}, 10, :def, "Some example"},
@@ -52,8 +52,16 @@ defmodule ExDoc.RetrieverTest do
test "get_docs returns an empty list if there's no docs info" do
file = "#{input_path}/__MAIN__/CompiledWithoutDocs.beam"
- [{ _, {_, doc} }] = R.get_docs([file], input_path)
+ [{ _, _, {_, doc} }] = R.get_docs([file], input_path)
assert_empty doc
end
+
+ test "get_docs returns a relative source path" do
+ file = "#{input_path}/__MAIN__/CompiledWithDocs.beam"
+
+ [{ _, path, _ }] = R.get_docs([file], input_path)
+
+ assert path == "test/fixtures/compiled_with_docs.ex"
+ end
end

0 comments on commit b754ffa

Please sign in to comment.