support for JavaScript imports

This commit is contained in:
Alan Hamlett 2018-03-11 13:29:30 -07:00
parent bc1d847e39
commit a212d48c57
17 changed files with 176 additions and 109 deletions

View file

View 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;

View file

@ -1,3 +0,0 @@
/**
* A Comment
*/

View file

@ -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'],
) )

View file

@ -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']
) )

View file

@ -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)

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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

View 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

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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."""