support for JavaScript imports
This commit is contained in:
parent
bc1d847e39
commit
a212d48c57
17 changed files with 176 additions and 109 deletions
0
tests/samples/codefiles/empty.ts
Normal file
0
tests/samples/codefiles/empty.ts
Normal file
37
tests/samples/codefiles/es6.js
Normal file
37
tests/samples/codefiles/es6.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import Alpha from './bravo';
|
||||||
|
import { charlie, delta } from '../../echo/foxtrot';
|
||||||
|
import golf from './hotel/india.js';
|
||||||
|
import juliett from 'kilo';
|
||||||
|
import {
|
||||||
|
lima,
|
||||||
|
mike,
|
||||||
|
} from './november';
|
||||||
|
import * from '/modules/oscar';
|
||||||
|
import * as papa from 'quebec';
|
||||||
|
import {romeo as sierra} from from 'tango.jsx';
|
||||||
|
import 'uniform.js';
|
||||||
|
import victorDefault, * as victorModule from '/modules/victor.js';
|
||||||
|
import whiskeyDefault, {whiskeyOne, whiskeyTwo} from 'whiskey';
|
||||||
|
|
||||||
|
const propTypes = {};
|
||||||
|
|
||||||
|
const defaultProps = {};
|
||||||
|
|
||||||
|
class Link extends Alpha.Component {
|
||||||
|
static method() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<a href={this.props.url} data-id={this.props.id}>
|
||||||
|
{this.props.text}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Link.propTypes = propTypes;
|
||||||
|
Link.defaultProps = defaultProps;
|
||||||
|
|
||||||
|
export default Link;
|
|
@ -1,3 +0,0 @@
|
||||||
/**
|
|
||||||
* A Comment
|
|
||||||
*/
|
|
|
@ -188,6 +188,28 @@ class DependenciesTestCase(TestCase):
|
||||||
entity='python.py',
|
entity='python.py',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_dependencies_still_detected_when_alternate_language_used(self):
|
||||||
|
with mock.patch('wakatime.stats.smart_guess_lexer') as mock_guess_lexer:
|
||||||
|
mock_guess_lexer.return_value = None
|
||||||
|
|
||||||
|
self.shared(
|
||||||
|
expected_dependencies=[
|
||||||
|
'app',
|
||||||
|
'django',
|
||||||
|
'flask',
|
||||||
|
'jinja',
|
||||||
|
'mock',
|
||||||
|
'pygments',
|
||||||
|
'simplejson',
|
||||||
|
'sqlalchemy',
|
||||||
|
'unittest',
|
||||||
|
],
|
||||||
|
expected_language='Python',
|
||||||
|
expected_lines=37,
|
||||||
|
entity='python.py',
|
||||||
|
extra_args=['--alternate-language', 'PYTHON'],
|
||||||
|
)
|
||||||
|
|
||||||
def test_python_dependencies_detected(self):
|
def test_python_dependencies_detected(self):
|
||||||
self.shared(
|
self.shared(
|
||||||
expected_dependencies=[
|
expected_dependencies=[
|
||||||
|
@ -302,7 +324,7 @@ class DependenciesTestCase(TestCase):
|
||||||
expected_dependencies=[
|
expected_dependencies=[
|
||||||
'"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"',
|
'"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"',
|
||||||
],
|
],
|
||||||
expected_language='HTML+PHP',
|
expected_language='HTML',
|
||||||
expected_lines=22,
|
expected_lines=22,
|
||||||
entity='html-with-php.html',
|
entity='html-with-php.html',
|
||||||
)
|
)
|
||||||
|
@ -312,7 +334,7 @@ class DependenciesTestCase(TestCase):
|
||||||
expected_dependencies=[
|
expected_dependencies=[
|
||||||
'"libs/json2.js"',
|
'"libs/json2.js"',
|
||||||
],
|
],
|
||||||
expected_language='HTML+Django/Jinja',
|
expected_language='HTML',
|
||||||
expected_lines=40,
|
expected_lines=40,
|
||||||
entity='html-django.html',
|
entity='html-django.html',
|
||||||
)
|
)
|
||||||
|
@ -336,24 +358,22 @@ class DependenciesTestCase(TestCase):
|
||||||
entity='go.go',
|
entity='go.go',
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_dependencies_still_detected_when_alternate_language_used(self):
|
def test_es6_dependencies_detected(self):
|
||||||
with mock.patch('wakatime.stats.smart_guess_lexer') as mock_guess_lexer:
|
|
||||||
mock_guess_lexer.return_value = None
|
|
||||||
|
|
||||||
self.shared(
|
self.shared(
|
||||||
expected_dependencies=[
|
expected_dependencies=[
|
||||||
'app',
|
'bravo',
|
||||||
'django',
|
'foxtrot',
|
||||||
'flask',
|
'india',
|
||||||
'jinja',
|
'kilo',
|
||||||
'mock',
|
'november',
|
||||||
'pygments',
|
'oscar',
|
||||||
'simplejson',
|
'quebec',
|
||||||
'sqlalchemy',
|
'tango',
|
||||||
'unittest',
|
'uniform',
|
||||||
|
'victor',
|
||||||
|
'whiskey',
|
||||||
],
|
],
|
||||||
expected_language='Python',
|
expected_language='JavaScript',
|
||||||
expected_lines=37,
|
expected_lines=37,
|
||||||
entity='python.py',
|
entity='es6.js',
|
||||||
extra_args=['--alternate-language', 'PYTHON'],
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -141,7 +141,7 @@ class LanguagesTestCase(utils.TestCase):
|
||||||
def test_typescript_detected_over_typoscript(self):
|
def test_typescript_detected_over_typoscript(self):
|
||||||
self.shared(
|
self.shared(
|
||||||
expected_language='TypeScript',
|
expected_language='TypeScript',
|
||||||
entity='typescript.ts',
|
entity='empty.ts',
|
||||||
extra_args=['--language', 'foo', '--plugin', 'NeoVim/703 vim-wakatime/4.0.9']
|
extra_args=['--language', 'foo', '--plugin', 'NeoVim/703 vim-wakatime/4.0.9']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -106,8 +106,8 @@ class DependencyParser(object):
|
||||||
self.lexer = lexer
|
self.lexer = lexer
|
||||||
|
|
||||||
if self.lexer:
|
if self.lexer:
|
||||||
module_name = self.lexer.__module__.rsplit('.', 1)[-1]
|
module_name = self.root_lexer.__module__.rsplit('.', 1)[-1]
|
||||||
class_name = self.lexer.__class__.__name__.replace('Lexer', 'Parser', 1)
|
class_name = self.root_lexer.__class__.__name__.replace('Lexer', 'Parser', 1)
|
||||||
else:
|
else:
|
||||||
module_name = 'unknown'
|
module_name = 'unknown'
|
||||||
class_name = 'UnknownParser'
|
class_name = 'UnknownParser'
|
||||||
|
@ -121,6 +121,14 @@ class DependencyParser(object):
|
||||||
except ImportError:
|
except ImportError:
|
||||||
log.debug('Parsing dependencies not supported for {0}.{1}'.format(module_name, class_name))
|
log.debug('Parsing dependencies not supported for {0}.{1}'.format(module_name, class_name))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def root_lexer(self):
|
||||||
|
if not self.lexer:
|
||||||
|
return None
|
||||||
|
if hasattr(self.lexer, 'root_lexer'):
|
||||||
|
return self.lexer.root_lexer
|
||||||
|
return self.lexer
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
if self.parser:
|
if self.parser:
|
||||||
plugin = self.parser(self.source_file, lexer=self.lexer)
|
plugin = self.parser(self.source_file, lexer=self.lexer)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.languages.c_cpp
|
wakatime.dependencies.c_cpp
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Parse dependencies from C++ code.
|
Parse dependencies from C++ code.
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.languages.data
|
wakatime.dependencies.data
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Parse dependencies from data files.
|
Parse dependencies from data files.
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.languages.dotnet
|
wakatime.dependencies.dotnet
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Parse dependencies from .NET code.
|
Parse dependencies from .NET code.
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.languages.go
|
wakatime.dependencies.go
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Parse dependencies from Go code.
|
Parse dependencies from Go code.
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.languages.templates
|
wakatime.dependencies.html
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Parse dependencies from Templates.
|
Parse dependencies from HTML.
|
||||||
|
|
||||||
:copyright: (c) 2014 Alan Hamlett.
|
:copyright: (c) 2014 Alan Hamlett.
|
||||||
:license: BSD, see LICENSE for more details.
|
:license: BSD, see LICENSE for more details.
|
||||||
|
@ -69,7 +69,7 @@ KEYWORDS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class HtmlDjangoParser(TokenParser):
|
class HtmlParser(TokenParser):
|
||||||
tags = []
|
tags = []
|
||||||
opening_tag = False
|
opening_tag = False
|
||||||
getting_attrs = False
|
getting_attrs = False
|
||||||
|
@ -141,63 +141,3 @@ class HtmlDjangoParser(TokenParser):
|
||||||
elif content.startswith('"') or content.startswith("'"):
|
elif content.startswith('"') or content.startswith("'"):
|
||||||
if self.current_attr_value is None:
|
if self.current_attr_value is None:
|
||||||
self.current_attr_value = content
|
self.current_attr_value = content
|
||||||
|
|
||||||
|
|
||||||
class VelocityHtmlParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MyghtyHtmlParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MasonParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MakoHtmlParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class CheetahHtmlParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class HtmlGenshiParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class RhtmlParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class HtmlPhpParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class HtmlSmartyParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class EvoqueHtmlParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ColdfusionHtmlParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class LassoHtmlParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class HandlebarsHtmlParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class YamlJinjaParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class TwigHtmlParser(HtmlDjangoParser):
|
|
||||||
pass
|
|
56
wakatime/dependencies/javascript.py
Normal file
56
wakatime/dependencies/javascript.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
wakatime.dependencies.javascript
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Parse dependencies from JavaScript code.
|
||||||
|
|
||||||
|
:copyright: (c) 2018 Alan Hamlett.
|
||||||
|
:license: BSD, see LICENSE for more details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from . import TokenParser
|
||||||
|
|
||||||
|
|
||||||
|
class JavascriptParser(TokenParser):
|
||||||
|
state = None
|
||||||
|
extension = re.compile(r'\.\w{1,4}$')
|
||||||
|
|
||||||
|
def parse(self):
|
||||||
|
for index, token, content in self.tokens:
|
||||||
|
self._process_token(token, content)
|
||||||
|
return self.dependencies
|
||||||
|
|
||||||
|
def _process_token(self, token, content):
|
||||||
|
if self.partial(token) == 'Reserved':
|
||||||
|
self._process_reserved(token, content)
|
||||||
|
elif self.partial(token) == 'Single':
|
||||||
|
self._process_string(token, content)
|
||||||
|
elif self.partial(token) == 'Punctuation':
|
||||||
|
self._process_punctuation(token, content)
|
||||||
|
else:
|
||||||
|
self._process_other(token, content)
|
||||||
|
|
||||||
|
def _process_reserved(self, token, content):
|
||||||
|
if self.state is None:
|
||||||
|
self.state = content
|
||||||
|
|
||||||
|
def _process_string(self, token, content):
|
||||||
|
if self.state == 'import':
|
||||||
|
self.append(self._format_module(content))
|
||||||
|
self.state = None
|
||||||
|
|
||||||
|
def _process_punctuation(self, token, content):
|
||||||
|
if content == ';':
|
||||||
|
self.state = None
|
||||||
|
|
||||||
|
def _process_other(self, token, content):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _format_module(self, content):
|
||||||
|
content = content.strip().strip('"').strip("'").strip()
|
||||||
|
content = content.split('/')[-1].split('\\')[-1]
|
||||||
|
content = self.extension.sub('', content, count=1)
|
||||||
|
return content
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.languages.java
|
wakatime.dependencies.java
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Parse dependencies from Java code.
|
Parse dependencies from Java code.
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.languages.php
|
wakatime.dependencies.php
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Parse dependencies from PHP code.
|
Parse dependencies from PHP code.
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.languages.python
|
wakatime.dependencies.python
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Parse dependencies from Python code.
|
Parse dependencies from Python code.
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.languages.unknown
|
wakatime.dependencies.unknown
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Parse dependencies from files of unknown language.
|
Parse dependencies from files of unknown language.
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,8 @@ def get_file_stats(file_name, entity_type='file', lineno=None, cursorpos=None,
|
||||||
if not language:
|
if not language:
|
||||||
language, lexer = guess_language(file_name)
|
language, lexer = guess_language(file_name)
|
||||||
|
|
||||||
|
language = use_root_language(language, lexer)
|
||||||
|
|
||||||
parser = DependencyParser(file_name, lexer)
|
parser = DependencyParser(file_name, lexer)
|
||||||
dependencies = parser.parse()
|
dependencies = parser.parse()
|
||||||
|
|
||||||
|
@ -236,6 +238,13 @@ def get_lexer(language):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def use_root_language(language, lexer):
|
||||||
|
if lexer and hasattr(lexer, 'root_lexer'):
|
||||||
|
return u(lexer.root_lexer.name)
|
||||||
|
|
||||||
|
return language
|
||||||
|
|
||||||
|
|
||||||
def get_language_from_json(language, key):
|
def get_language_from_json(language, key):
|
||||||
"""Finds the given language in a json file."""
|
"""Finds the given language in a json file."""
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue