Skip to content

Commit

Permalink
fix(providers): added auto close for quotes and brackets for tss (#76)
Browse files Browse the repository at this point in the history
* fix(providers): added auto close for quotes and brackets for tss

Added auto closing for quotes and brackets in the tss file and modified the style auto complete to
behave the same for know tags

* fix(providers): addressed comments and converted tm file to json

* fix(providers): improved regex and fixed rules

* chore(triggers): addressed comments
  • Loading branch information
longton95 authored and ewanharris committed May 1, 2019
1 parent 24799ad commit bfedfe1
Show file tree
Hide file tree
Showing 7 changed files with 434 additions and 42 deletions.
341 changes: 341 additions & 0 deletions grammars/tss.JSON-tmLanguage.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Expand Up @@ -49,14 +49,15 @@
],
"extensions": [
".tss"
]
],
"configuration": "./tssConf.json"
}
],
"grammars": [
{
"language": "alloy-tss",
"scopeName": "source.css.tss",
"path": "./grammars/tss.tmLanguage"
"path": "./grammars/tss.JSON-tmLanguage.json"
}
],
"commands": [
Expand Down
2 changes: 1 addition & 1 deletion src/extension.ts
Expand Up @@ -74,7 +74,7 @@ function activate (context) {
context.subscriptions.push(
// register completion providers
vscode.languages.registerCompletionItemProvider({ scheme: 'file', pattern: viewFilePattern }, new ViewCompletionItemProvider(), '.', '\'', '"'),
vscode.languages.registerCompletionItemProvider({ scheme: 'file', pattern: styleFilePattern }, new StyleCompletionItemProvider()),
vscode.languages.registerCompletionItemProvider({ scheme: 'file', pattern: styleFilePattern }, new StyleCompletionItemProvider(), '.', '\'', '"'),
vscode.languages.registerCompletionItemProvider({ scheme: 'file', pattern: controllerFilePattern }, new ControllerCompletionItemProvider(), '.', '\'', '"', '/'),
vscode.languages.registerCompletionItemProvider({ scheme: 'file', pattern: '**/tiapp.xml' }, new TiappCompletionItemProvider(), '.'),

Expand Down
48 changes: 25 additions & 23 deletions src/providers/completion/alloyAutoCompleteRules.ts
Expand Up @@ -7,7 +7,7 @@ import { parseString } from 'xml2js';
import { ExtensionContainer } from '../../container';

export const cfgAutoComplete = {
regExp: /Alloy\.CFG\.([-a-zA-Z0-9-_/]*)$/,
regExp: /Alloy\.CFG\.([-a-zA-Z0-9-_/]*)[,]?$/,
async getCompletions () {
const cfgPath = path.join(utils.getAlloyRootPath(), 'config.json');
const completions = [];
Expand Down Expand Up @@ -36,33 +36,35 @@ export const cfgAutoComplete = {
};

export const i18nAutoComplete = {
regExp: /(L\(|titleid\s*[:=]\s*)["'](\w*)$/,
async getCompletions () {
const defaultLang = ExtensionContainer.config.project.defaultI18nLanguage;
const i18nPath = utils.getI18nPath();
if (utils.directoryExists(i18nPath)) {
const i18nStringPath = path.join(i18nPath, defaultLang, 'strings.xml');
const completions = [];
if (utils.fileExists(i18nStringPath)) {
const document = await workspace.openTextDocument(i18nStringPath);
parseString(document.getText(), (error, result) => {
if (result && result.resources && result.resources.string) {
for (const value of result.resources.string) {
completions.push({
label: value.$.name,
kind: CompletionItemKind.Reference,
detail: value._
});
regExp: /(L\(|titleid\s*[:=]\s*)["'](\w*["']?)$/,
getCompletions () {
return new Promise(async (resolve, reject) => {
const defaultLang = ExtensionContainer.config.project.defaultI18nLanguage;
const i18nPath = utils.getI18nPath();
if (utils.directoryExists(i18nPath)) {
const i18nStringPath = path.join(i18nPath, defaultLang, 'strings.xml');
const completions = [];
if (utils.fileExists(i18nStringPath)) {
const document = await workspace.openTextDocument(i18nStringPath);
parseString(document.getText(), (error, result) => {
if (result && result.resources && result.resources.string) {
for (const value of result.resources.string) {
completions.push({
label: value.$.name,
kind: CompletionItemKind.Reference,
detail: value._
});
}
return resolve(completions);
}
return completions;
}
});
});
}
}
}
});
}
};
export const imageAutoComplete = {
regExp: /image\s*[:=]\s*["']([\w\s\\/\-_():.]*)$/,
regExp: /image\s*[:=]\s*["']([\w\s\\/\-_():.]*)['"]?$/,
getCompletions () {
const alloyRootPath = utils.getAlloyRootPath();
const assetPath = path.join(alloyRootPath, 'assets');
Expand Down
36 changes: 21 additions & 15 deletions src/providers/completion/styleCompletionItemProvider.ts
Expand Up @@ -21,16 +21,15 @@ export class StyleCompletionItemProvider implements CompletionItemProvider {
* @returns {Thenable|Array}
*/
public async provideCompletionItems (document, position) {
const linePrefix = document.getText(new Range(position.line, 0, position.line, position.character));
const linePrefix = document.getText(new Range(position.line, 0, position.line, position.character + 1));
const prefixRange = document.getWordRangeAtPosition(position);
const prefix = prefixRange ? document.getText(prefixRange) : null;

if (!this.completions) {
await this.loadCompletions();
}

// property value - foo: _ or foo: ba_
if (/\s*\w+\s*:\s*[\w"'.]*$/.test(linePrefix)) {
if (/\s*\w+\s*:\s*\w*[(]?["'.]?\w*["'.]?[,]?$/.test(linePrefix)) {
// first attempt Alloy rules (i18n, image etc.)
let ruleResult;
for (const rule of Object.values(alloyAutoCompleteRules)) {
Expand All @@ -43,15 +42,15 @@ export class StyleCompletionItemProvider implements CompletionItemProvider {
} else {
return this.getPropertyValueCompletions(linePrefix, prefix);
}
// property name - _ or fo_
// property name - _ or fo_
} else if (/^\s*\w*$/.test(linePrefix)) {
return this.getPropertyNameCompletions(linePrefix, prefix, position, document);
// class or id - ".foo_ or "#foo
} else if (/^['"][.#]\w*$/.test(linePrefix)) {
return this.getClassOrIdCompletions(linePrefix, prefix);
} else if (/^\s*['"][.#][\w*]["']?$/.test(linePrefix)) {
return this.getClassOrIdCompletions(linePrefix, prefix, position, document);
// tag - "Wind_ or "_
} else if (/^['"]\w*$/.test(linePrefix)) {
return this.getTagCompletions(linePrefix, prefix);
} else if (/^\s*['"][\w*]["']?$/.test(linePrefix)) {
return this.getTagCompletions(linePrefix, prefix, position, document);
}
}

Expand All @@ -63,24 +62,28 @@ export class StyleCompletionItemProvider implements CompletionItemProvider {
*
* @returns {Thenable}
*/
public getClassOrIdCompletions (linePrefix, prefix) {
public getClassOrIdCompletions (linePrefix, prefix, position, document) {
return new Promise(resolve => {
const relatedFile = related.getTargetPath('xml');
const fileName = relatedFile.split('/').pop();
workspace.openTextDocument(relatedFile).then(document => {
const quote = /'/.test(linePrefix) ? '\'' : '\"';
const range = document.getWordRangeAtPosition(position, /\w+["']/);
workspace.openTextDocument(relatedFile).then(file => {
const completions = [];
const values = [];
let regex = /class="(.*?)"/g;
if (/^['"]#\w*$/.test(linePrefix)) {
if (/^['"]#\w*["']?$/.test(linePrefix)) {
regex = /id="(.*?)"/g;
}
for (let matches = regex.exec(document.getText()); matches !== null; matches = regex.exec(document.getText())) {
for (let matches = regex.exec(file.getText()); matches !== null; matches = regex.exec(file.getText())) {
for (const value of matches[1].split(' ')) {
if (value && value.length > 0 && !values.includes(value) && (!prefix || completionItemProviderHelper.matches(value, prefix))) {
completions.push({
label: value,
kind: CompletionItemKind.Reference,
detail: `${fileName}`
detail: `${fileName}`,
range,
insertText: new SnippetString(`${value}${quote}: {\n\t\${1}\t\n}`)
});
values.push(value);
}
Expand All @@ -99,15 +102,18 @@ export class StyleCompletionItemProvider implements CompletionItemProvider {
*
* @returns {Array}
*/
public getTagCompletions (linePrefix, prefix) {
public getTagCompletions (linePrefix, prefix, position, document) {
const completions = [];
const range = document.getWordRangeAtPosition(position, /\w+["']/);
const quote = /'/.test(linePrefix) ? '\'' : '\"';
for (const [ key, value ] of Object.entries(this.completions.alloy.tags) as any[]) {
if (!prefix || completionItemProviderHelper.matches(key, prefix)) {
completions.push({
label: key,
kind: CompletionItemKind.Class,
detail: value.apiName,
insertText: new SnippetString(`${key}": {\n\t\${1}\t\n}`)
range,
insertText: new SnippetString(`${key}${quote}: {\n\t\${1}\t\n}`)
});
}
}
Expand Down
3 changes: 2 additions & 1 deletion tslint.json
Expand Up @@ -33,7 +33,8 @@
},
"linterOptions": {
"exclude": [
"scripts/*.js"
"scripts/*.js",
"grammars/*.json"
]
}
}
41 changes: 41 additions & 0 deletions tssConf.json
@@ -0,0 +1,41 @@
{
"comments": {
"lineComment": "//",
"blockComment": ["/*", "*/"]
},
"brackets": [
["{", "}"],
["[", "]"],
["(", ")"]
],
"autoClosingPairs": [{
"open": "{",
"close": "}"
},
{
"open": "[",
"close": "]"
},
{
"open": "(",
"close": ")"
},
{
"open": "'",
"close": "'",
"notIn": ["string"]
},
{
"open": "\"",
"close": "\"",
"notIn": ["string", "comment"]
}
],
"surroundingPairs": [
["{", "}"],
["[", "]"],
["(", ")"],
["'", "'"],
["\"", "\""]
]
}

0 comments on commit bfedfe1

Please sign in to comment.