Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue: a new parser (partially implemented) #1581

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

masatake
Copy link
Member

This is a stub. Following must be solved.

  • parsing "export default" in <script></script> ara, and
  • choosing a guest parser dynamically.

Signed-off-by: Masatake YAMATO yamato@redhat.com

This is a stub. Following must be solved.

* parsing "export default" in <script></script> ara, and
* choosing a guest parser dynamically.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.06%) to 85.905% when pulling ce2225c on masatake:vue-parser into 8465ce7 on universal-ctags:master.

Just for evaluating vue parser.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
@masatake
Copy link
Member Author

[yamato@master]~/var/ctags-github% cat ./foo.vue
<template>
  <div class="example">{{ msg }}</div>
</template>

<script>
import _ from 'underscore'
import MTableRow from './m-table-row'
let eachColumn = {
  'data': [],  // do not want to match this!
  'subfields': {},
}

function abyb (a, b) {

}

export default {
  name: 'm-table',
  props: {
    'data': {
      'type': [Object],
      'default': function () {
        return {
          'columns': [],
          'fixColumnCount': null
        }
      }
    }
  },
  data () { // want to match this
    return {
      'addable': false,
      'deletable': false
    }
  },
  computed: {
    style () {
    },
    headerIDStr: {
      cache: false,
      get () {
      }
    }
  },
  'methods': {
    initData () {
    },
    getColumn (index) {
    },
    getColumnShow (index) {
    },
    updateColumnSort () {
    },
    getData (data, index) {
    },
    updateRowSort (sortBy) {
    },
    onMouseOverHeader () {
    }
  },
  created () {
    this.initData()
  },
  components: {MTableRow}
}
</script>

<style>
.example {
  color: red;
}
</style>

<custom1>
  This could be e.g. documentation for the component.
</custom1>

[yamato@master]~/var/ctags-github% ./ctags --extras=+g --sort=no -o - ./foo.vue
data	./foo.vue	/^  'data': [],  \/\/ do not want to match this!$/;"	p	class:import
subfields	./foo.vue	/^  'subfields': {},$/;"	p	class:import
import	./foo.vue	/^import _ from 'underscore'$/;"	c
abyb	./foo.vue	/^function abyb (a, b) {$/;"	f
name	./foo.vue	/^  name: 'm-table',$/;"	p	class:default
type	./foo.vue	/^      'type': [Object],$/;"	p	class:default.props.data
default	./foo.vue	/^      'default': function () {$/;"	m	class:default.props.data
data	./foo.vue	/^    'data': {$/;"	c	class:default.props
props	./foo.vue	/^  props: {$/;"	c	class:default
data	./foo.vue	/^  data () { \/\/ want to match this$/;"	m	class:default
style	./foo.vue	/^    style () {$/;"	m	class:default.computed
cache	./foo.vue	/^      cache: false,$/;"	p	class:default.computed.headerIDStr
get	./foo.vue	/^      get () {$/;"	m	class:default.computed.headerIDStr
headerIDStr	./foo.vue	/^    headerIDStr: {$/;"	c	class:default.computed
computed	./foo.vue	/^  computed: {$/;"	c	class:default
initData	./foo.vue	/^    initData () {$/;"	m	class:default.methods
getColumn	./foo.vue	/^    getColumn (index) {$/;"	m	class:default.methods
getColumnShow	./foo.vue	/^    getColumnShow (index) {$/;"	m	class:default.methods
updateColumnSort	./foo.vue	/^    updateColumnSort () {$/;"	m	class:default.methods
getData	./foo.vue	/^    getData (data, index) {$/;"	m	class:default.methods
updateRowSort	./foo.vue	/^    updateRowSort (sortBy) {$/;"	m	class:default.methods
onMouseOverHeader	./foo.vue	/^    onMouseOverHeader () {$/;"	m	class:default.methods
methods	./foo.vue	/^  'methods': {$/;"	c	class:default
created	./foo.vue	/^  created () {$/;"	m	class:default
components	./foo.vue	/^  components: {MTableRow}$/;"	p	class:default
.example	./foo.vue	/.example {$/;"	c

It seems that import is not handled well.
I can implement VueJavaScript subparser on JavaScript base parser with following way.

  1. JavaScript parser calls a sub parser (here VueJavaScript parser) when making a tag.
    The sub parser can receive the tagEntryInfo.
  2. VueJavaScript parser inspect the received tagEntryInfo.
    If it has default as scope, VueJavaScript parser gets more interest.
  3. If it has one of name, data, props, computed, methods, created as sub scope like 'default.name',
    it is really interesting. VueJavaScript parser copies the tagEntryInfo.
    VueJavaScript parser modifies the copied one; set its langType field to "VueJavaScript".
    Call makeTagEntry.

@Fmajor
Copy link

Fmajor commented Oct 21, 2017

i have make error

RST2MAN   man/ctags.1
/bin/sh: /usr/local/bin/rst2man.py: /usr/local/opt/python3/bin/python3.5: bad interpreter: No such file or directory
make[1]: *** [man/ctags.1] Error 126
make: *** [all] Error 2

my python is 3.6, i make a soft link to solve this. These seems like a bug in configuration about the python path

@Fmajor Fmajor mentioned this pull request Oct 21, 2017
@Fmajor
Copy link

Fmajor commented Oct 21, 2017

some plugins like tagbar in vim will not list tags of kinds unless they are list in ctags --list-kinds=Vue, can you add all the kinds in HTML, CSS and Javascript into the output of ctags --list-kinds=Vue?

@codebrainz
Copy link
Contributor

These seems like a bug in configuration about the python path

What is the shebang line on your rst2man.py and does the script come from your package manager? The code at the end of Makefile.am looks reasonable, but I'm not sure what's going on with the non-Autotools man/Makefile, it seems to be doing the same but in a non-portable manner.

@Fmajor
Copy link

Fmajor commented Oct 21, 2017

after i install the latest version from homebrew for one time, the make error is automatically solved, i don't know why...

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
To minimize a parser accessing kindDefinition data type, this commit
changes the type `kind' and `extensions.scopeKind' fields to int.

With this change, a parser can inspect a tagEntryInfo made in
another parser. In other word, communication between parsers
via tagEntryInfo is much easier.

Actuall example will be shown in the communiation between
JavaScript parser and VueJavaScript parser.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
@masatake
Copy link
Member Author

#1584 is needed to write VueJavaScript parser which focuses only on the first level keys in 'export default' block. JavaScript parser notifies all tags captured in the parser to VueJavaScript sub parser.
VueJavaScript subparsre inspects the passed tags and whether VueJavaScript subparser should emit the tag with langType = VueJavaScript parser or not. To inspect a tag, VueJavaScript subparser may need #1584.

For showing my idea, I will push the changes in #1584, I will merge to the branch I proposed in this #1581.
#1584 itself is worth merging regardless of supporting Vue.

Input (foo.vue):

     1	<template>
     2	  <div class="example">{{ msg }}</div>
     3	</template>
     4
     5	<script>
     6	import _ from 'underscore'
     7	import MTableRow from './m-table-row'
     8	let eachColumn = {
     9	  'data': [],  // do not want to match this!
    10	  'subfields': {},
    11	}
    12
    13	function abyb (a, b) {
    14
    15	}
    16
    17	export default {
    18	  name: 'm-table',
    19	  props: {
    20	    'data': {
    21	      'type': [Object],
    22	      'default': function () {
    23	        return {
    24	          'columns': [],
    25	          'fixColumnCount': null
    26	        }
    27	      }
    28	    }
    29	  },
    30	  data () { // want to match this
    31	    return {
    32	      'addable': false,
    33	      'deletable': false
    34	    }
    35	  },
    36	  computed: {
    37	    style () {
    38	    },
    39	    headerIDStr: {
    40	      cache: false,
    41	      get () {
    42	      }
    43	    }
    44	  },
    45	  'methods': {
    46	    initData () {
    47	    },
    48	    getColumn (index) {
    49	    },
    50	    getColumnShow (index) {
    51	    },
    52	    updateColumnSort () {
    53	    },
    54	    getData (data, index) {
    55	    },
    56	    updateRowSort (sortBy) {
    57	    },
    58	    onMouseOverHeader () {
    59	    }
    60	  },
    61	  created () {
    62	    this.initData()
    63	  },
    64	  components: {MTableRow}
    65	}
    66	</script>
    67
    68	<style>
    69	.example {
    70	  color: red;
    71	}
    72	</style>
    73
    74	<custom1>
    75	  This could be e.g. documentation for the component.
    76	</custom1>

Output with "./ctags --sort=no --fields=+lKn --extras=+g -o - foo.vue | grep -v language:JavaScript"

    name	foo.vue	/^  name: 'm-table',$/;"	property	line:17	language:VueJavaScript	class:default
    data	foo.vue	/^    'data': {$/;"	class	line:19	language:VueJavaScript	class:default.props
    props	foo.vue	/^  props: {$/;"	class	line:18	language:VueJavaScript	class:default
    data	foo.vue	/^  data () { \/\/ want to match this$/;"	method	line:29	language:VueJavaScript	class:default
    style	foo.vue	/^    style () {$/;"	method	line:36	language:VueJavaScript	class:default.computed
    headerIDStr	foo.vue	/^    headerIDStr: {$/;"	class	line:38	language:VueJavaScript	class:default.computed
    computed	foo.vue	/^  computed: {$/;"	class	line:35	language:VueJavaScript	class:default
    initData	foo.vue	/^    initData () {$/;"	method	line:45	language:VueJavaScript	class:default.methods
    getColumn	foo.vue	/^    getColumn (index) {$/;"	method	line:47	language:VueJavaScript	class:default.methods
    getColumnShow	foo.vue	/^    getColumnShow (index) {$/;"	method	line:49	language:VueJavaScript	class:default.methods
    updateColumnSort	foo.vue	/^    updateColumnSort () {$/;"	method	line:51	language:VueJavaScript	class:default.methods
    getData	foo.vue	/^    getData (data, index) {$/;"	method	line:53	language:VueJavaScript	class:default.methods
    updateRowSort	foo.vue	/^    updateRowSort (sortBy) {$/;"	method	line:55	language:VueJavaScript	class:default.methods
    onMouseOverHeader	foo.vue	/^    onMouseOverHeader () {$/;"	method	line:57	language:VueJavaScript	class:default.methods
    methods	foo.vue	/^  'methods': {$/;"	class	line:44	language:VueJavaScript	class:default
    created	foo.vue	/^  created () {$/;"	method	line:60	language:VueJavaScript	class:default
    components	foo.vue	/^  components: {MTableRow}$/;"	property	line:63	language:VueJavaScript	class:default
    .example	foo.vue	/.example {$/;"	class	line:68	language:CSS

TODO: The "grep -v" should be able to be removed when "--languages=-JavaScript" is passed.
CAVEAT: The order of tags are expected, not a bug.
TODO: This implementation tracks the level two keys in "export default".
      Though @Fmajor dosn't want ctags to track structures too deep, I wonder
      such truncating is a job of ctags or not. Such things can be done with
      clinet tools.
TODO: It seems that export keyword is not a part of JavaScript yet.
      Transpilers handle it. However, it will be nice if JavaScript parser
      supports it.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
@masatake
Copy link
Member Author

See 61d77c8.

@Fmajor
Copy link

Fmajor commented Oct 23, 2017

great! get what i want.
thanks a lot!

@Fmajor
Copy link

Fmajor commented Oct 26, 2017

now i get

$ ctags --list-kinds=Vue
$ ctags --list-kinds=VueJavaScript                                                                                                                                                 
f  functions
c  classes
m  methods
p  properties
C  constants
v  global variables
g  generators

can you add the kinds into ctags --list-kinds=Vue?

@masatake
Copy link
Member Author

I am trying to add a flag to mline and mtable parsrers launching a guest parser from a host parser defined in an option file.
I had to fix many things, but now it works. The flag may the vue parser much simple.

[jet@living]~/var/ctags% cat input.vue
cat input.vue
<template>
  <p id="slot">{{ hello }}</p>
</template>

<script>
// https://flaviocopes.com/vue-single-file-components/
var x;
export default {
  data() {
    return {
      hello: 'Hello World!'
    }
  }
}
</script>

<style scoped>
  p {
    color: blue;
  }
</style>
[jet@living]~/var/ctags% cat vue.ctags
cat vue.ctags
--langdef=Vue
--map-Vue=.vue

--mline-regex-Vue=/<template>\n((.|\n){1,}\n)<\/template>//{guest=HTML,1start,1end}
--mline-regex-Vue=/<script>\n((.|\n){1,}\n)<\/script>//{guest=JavaScript,1start,1end}
--mline-regex-Vue=/<style([ ]{1,}[a-z]{1,})*>\n((.|\n){1,}\n)<\/style>//{guest=CSS,2start,2end}


[jet@living]~/var/ctags% ./ctags --extras=+g -o - --options=/home/jet/var/ctags/vue.ctags input.vue
./ctags --extras=+g -o - --options=/home/jet/var/ctags/vue.ctags input.vue
p	input.vue	/^  p {$/;"	s
slot	input.vue	/^  <p id="slot">{{ hello }}<\/p>$/;"	I
x	input.vue	/^var x;$/;"	v
[jet@living]~/var/ctags% ./ctags --fields=+l --extras=+g -o - --options=/home/jet/var/ctags/vue.ctags input.vue
./ctags --fields=+l --extras=+g -o - --options=/home/jet/var/ctags/vue.ctags input.vue
p	input.vue	/^  p {$/;"	s	language:CSS
slot	input.vue	/^  <p id="slot">{{ hello }}<\/p>$/;"	I	language:HTML
x	input.vue	/^var x;$/;"	v	language:JavaScript

masatake added a commit to masatake/ctags that referenced this pull request Jun 23, 2019
Continuation of universal-ctags#1581.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
@masatake
Copy link
Member Author

Thank you for discussing.
I implemented guest flag I write in the last comment.
See #2123.
I would like to withdraw the change proposed in this pull request.
#2123 is much better.

masatake added a commit to masatake/ctags that referenced this pull request Jun 23, 2019
Continuation of universal-ctags#1581.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
masatake added a commit to masatake/ctags that referenced this pull request Jun 23, 2019
Continuation of universal-ctags#1581.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
masatake added a commit to masatake/ctags that referenced this pull request Jun 23, 2019
Continuation of universal-ctags#1581.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants