Skip to content

Commit

Permalink
Implement source locations provider for JS component symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
alexprey committed Jan 22, 2019
1 parent e3227d7 commit 2bd9426
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ All notable changes to the "svelte-intellisense" extension will be documented in

Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.

## [1.2.0] UNRELEASED

- [Added] Implement source locations provider for most of component symbols.

## [1.1.5] 07.12.2018

- [Fixed] Fix and refactor param keyword parsing to handle some wrong cases (fix and close issue #7)
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ npm install --save sveltedoc-parser
- Extract component helpers
- Extract component actions
- Extract component transitions
- Extract source locations for component symbols

## Configuration

Expand All @@ -48,6 +49,7 @@ npm install --save sveltedoc-parser
| **encoding** | The file encoding. | `utf8` |
| **features** | The component features to parse and extracting. | By default used all supported features (see below). |
| **ignoredVisibilities** | The list of ignored visibilities. | `['private', 'protected']` |
| **includeSourceLocations** | Flag, which indicates that source locations should be provided for component symbols. | `false` |

### Supported feature names

Expand Down
9 changes: 7 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ function extractContentFromHtmlBlock(content, blockName) {
let leftContent = content;
let innerBlockContent = '';
let attributes = '';
let offset = 0;

const blockStart = leftContent.indexOf(`<${blockName}`);

Expand All @@ -105,6 +106,7 @@ function extractContentFromHtmlBlock(content, blockName) {

attributes = leftContent.substr(blockStart + blockName.length + 1, openTagEndIndex - blockStart - blockName.length - 1);
innerBlockContent = leftContent.substr(openTagEndIndex + 1, blockEnd - openTagEndIndex - 1);
offset = openTagEndIndex + 1;

leftContent = leftContent.substr(0, blockStart) + leftContent.substr(blockEnd + blockName.length + 3);
}
Expand All @@ -113,7 +115,8 @@ function extractContentFromHtmlBlock(content, blockName) {
return {
leftContent: leftContent,
innerContent: innerBlockContent,
attributes: attributes
attributes: attributes,
offset: offset
};
}

Expand All @@ -124,6 +127,8 @@ function loadSourceFromFileContent(fileContent) {
return {
template: style.leftContent,
script: script.innerContent,
style: style.innerContent
scriptOffset: script.offset,
style: style.innerContent,
styleOffset: style.offset
};
}
17 changes: 17 additions & 0 deletions lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const utils = require('./utils');
const jsdoc = require('./jsdoc');

const DEFAULT_OPTIONS = {
/**
* Flag, indicating that source locations should be extracted from source.
*/
includeSourceLocations: false,
range: false,
// comment: true,
attachComment: true,
Expand Down Expand Up @@ -54,6 +58,8 @@ class Parser extends EventEmitter {
this.features = options.features || SUPPORTED_FEATURES;

if (options.source.hasOwnProperty('script') && options.source.script) {
this.scriptOffset = options.source.scriptOffset || 0;

try {
this.ast = espree.parse(options.source.script, options);
} catch (e) {
Expand All @@ -62,9 +68,11 @@ class Parser extends EventEmitter {
this.ast = espree.parse(script, options);
}
} else {
this.scriptOffset = 0;
this.ast = null;
}

this.includeSourceLocations = options.includeSourceLocations;
this.componentName = null;
this.template = options.source.template;
this.filename = options.filename;
Expand Down Expand Up @@ -137,6 +145,15 @@ class Parser extends EventEmitter {
entry.name = Object.keys(entry.value)[0];
entry.value = entry.value[entry.name];

if (this.includeSourceLocations) {
if (p.key && p.key.start >= 0 && p.key.end >= p.key.start) {
entry.loc = {
start: p.key.start + this.scriptOffset,
end: p.key.end + this.scriptOffset
};
}
}

if (property.key.name === 'computed') {
if (entry.value instanceof utils.NodeFunction) {
entry.dependencies = utils.getDependencies(
Expand Down
28 changes: 28 additions & 0 deletions test/integration/locations/locations.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const path = require('path');
const chai = require('chai');
const expect = chai.expect;

const parser = require('../../../index');

describe('SvelteDoc - Source locations', () => {
it('Source locations for component data properties should be extracted', (done) => {
parser.parse({
includeSourceLocations: true,
filename: path.resolve(__dirname, 'main.svelte'),
features: ['data', 'methods'],
ignoredVisibilities: []
}).then((doc) => {
expect(doc.data.length).is.equals(1);
const property = doc.data[0];

expect(property.loc).is.deep.equals({
start: 89,
end: 99
});

done();
}).catch(e => {
done(e);
});
});
});
18 changes: 18 additions & 0 deletions test/integration/locations/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div>
</div>

<script>
export default {
data() {
return {
inlineTest: ''
}
},
methods: {
hello() {
console.log('hello');
},
helloV2: () => console.log('hello v2')
}
}
</script>
86 changes: 81 additions & 5 deletions test/integration/overall/overall.main.doc.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
"description": "The skin type for layout.",
"value": "default",
"name": "skin",
"loc": {
"start": 1128,
"end": 1132
},
"type": {
"kind": "union",
"text": "'default'|'night'",
Expand Down Expand Up @@ -41,6 +45,10 @@
"visibility": "public",
"description": "The list of menu items.",
"name": "menuItems",
"loc": {
"start": 1256,
"end": 1265
},
"type": {
"kind": "type",
"text": "Array<any>",
Expand All @@ -62,6 +70,10 @@
"description": "The page header.",
"value": "",
"name": "pageHeader",
"loc": {
"start": 1406,
"end": 1416
},
"type": {
"kind": "type",
"text": "string",
Expand All @@ -83,6 +95,10 @@
"description": "The page content.",
"value": "",
"name": "pageContent",
"loc": {
"start": 1558,
"end": 1569
},
"type": {
"kind": "type",
"text": "string",
Expand All @@ -95,6 +111,10 @@
"keywords": [],
"value": false,
"name": "showSkinSelector",
"loc": {
"start": 1588,
"end": 1604
},
"type": {
"kind": "type",
"text": "boolean",
Expand All @@ -107,6 +127,10 @@
"keywords": [],
"value": {},
"name": "userKpiData",
"loc": {
"start": 1626,
"end": 1637
},
"type": {
"kind": "type",
"text": "any",
Expand All @@ -119,6 +143,10 @@
"keywords": [],
"value": 10,
"name": "newsFeedUpdateTimeout",
"loc": {
"start": 1656,
"end": 1677
},
"type": {
"kind": "type",
"text": "number",
Expand All @@ -131,6 +159,10 @@
"keywords": [],
"value": "",
"name": "copyright",
"loc": {
"start": 1696,
"end": 1705
},
"type": {
"kind": "type",
"text": "string",
Expand All @@ -144,6 +176,10 @@
"visibility": "public",
"description": "Indicates that mobile device are used.",
"name": "isMobile",
"loc": {
"start": 1834,
"end": 1842
},
"dependencies": [
"_"
]
Expand All @@ -153,6 +189,10 @@
"description": null,
"keywords": [],
"name": "hasMenu",
"loc": {
"start": 1890,
"end": 1897
},
"dependencies": [
"menuItems"
]
Expand All @@ -169,6 +209,10 @@
"visibility": "public",
"description": "Do some action based on action name value",
"name": "doAction",
"loc": {
"start": 2191,
"end": 2199
},
"args": [
"actionName"
],
Expand Down Expand Up @@ -196,6 +240,10 @@
"visibility": "private",
"description": "",
"name": "handleSkinChanged",
"loc": {
"start": 2262,
"end": 2279
},
"args": [
"event"
]
Expand All @@ -207,6 +255,10 @@
"description": null,
"keywords": [],
"name": "tooltip",
"loc": {
"start": 2457,
"end": 2464
},
"args": [
"node"
]
Expand All @@ -218,7 +270,11 @@
"description": null,
"keywords": [],
"value": "window",
"name": "window"
"name": "window",
"loc": {
"start": 1985,
"end": 1991
}
}
],
"components": [
Expand All @@ -227,28 +283,44 @@
"description": null,
"keywords": [],
"value": "./Header.svelte",
"name": "Header"
"name": "Header",
"loc": {
"start": 805,
"end": 811
}
},
{
"visibility": "public",
"description": null,
"keywords": [],
"value": "./Menu.svelte",
"name": "Menu"
"name": "Menu",
"loc": {
"start": 841,
"end": 845
}
},
{
"visibility": "public",
"description": null,
"keywords": [],
"value": "./MenuItem.svelte",
"name": "MenuItem"
"name": "MenuItem",
"loc": {
"start": 873,
"end": 881
}
},
{
"visibility": "public",
"description": null,
"keywords": [],
"value": "./MarkdownContent.svelte",
"name": "MarkdownContent"
"name": "MarkdownContent",
"loc": {
"start": 913,
"end": 928
}
}
],
"description": "The entry-point component for 'Overall' page of Web-Application.",
Expand Down Expand Up @@ -277,6 +349,10 @@
"description": null,
"keywords": [],
"name": "delay",
"loc": {
"start": 2683,
"end": 2688
},
"args": [
"node"
]
Expand Down
1 change: 1 addition & 0 deletions test/integration/overall/overall.main.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const parser = require('../../../index');
describe('SvelteDoc - Overall', () => {
it('Component should be parsed with all features', (done) => {
parser.parse({
includeSourceLocations: true,
filename: path.resolve(__dirname, 'main.svelte'),
ignoredVisibilities: []
}).then((doc) => {
Expand Down
Loading

0 comments on commit 2bd9426

Please sign in to comment.