Skip to content

Commit

Permalink
Merge pull request #2 from anzwdev/master
Browse files Browse the repository at this point in the history
Update
  • Loading branch information
f4n0 authored Jan 14, 2020
2 parents 57a1c69 + 736367d commit 9efaa12
Show file tree
Hide file tree
Showing 51 changed files with 1,436 additions and 265 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Change Log

## 1.0.25
- Symbols service added to the extension API

## 1.0.24
- Code analyzers rules viewer added after Dmitry Katson request
- Html/js table control bugfixes

Thank you Dmitry for your request

## 1.0.23
- Syntax tree visualizer added. It shows current document syntax tree that can help developers to create their own al code analyzers.
- Support for Area and UserControl elements added to "Add multiple fields" code action on pages

## 1.0.22
- Github issue #60 - Enable Object Navigation via Symbols Tree
- Github issue #61 - Open documents on multiple tabs from "Go to definition" in "AL Object Browser". To enable this functionality please change "alOutline.openDefinitionInNewTab" setting to true
- Github issue #62 - Event publishers support added to the xml documentation
- XML documentation is enabled by default now, to turn it off change "alOutline.docCommentsType" setting to "none"
- obsolete "enableFeaturePreview" setting removed

Thank you pri-kise, kevindstanley1988 and stefanoPrimo for reporting your issues and suggestions

## 1.0.21
- Github issue #56 fixed - quick search in symbols tree ignores double quotes now

Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ This extension was originally named 'AL Code Outline' because it started as AL c
- Code actions
- Action images browser
- Documentation comments support
- Code analyzers rules viewer
- Document syntax visualizer

### AL objects wizards

Expand Down Expand Up @@ -91,10 +93,21 @@ Extension adds new "AZ AL Dev Tools: Show Action Images" command to the "Command

### Documentation comments support

When developer types "///" in a line above a symbol declaration (i.e. variable, procedure, field), extension can add "Xml Documentation Comments" to the list of available completion items. When it is selected, xml documentation snippet will be inserted into the code editor. If symbol below cursor is a procedure declaration, inserted snippet will contail all procedure parameters. This functionality can be turned off and on by changing "alOutline.docCommentsType" setting to "none" or "xml". By default it is turned off.
When developer types "///" in a line above a symbol declaration (i.e. variable, procedure, field), extension can add "Xml Documentation Comments" to the list of available completion items. When it is selected, xml documentation snippet will be inserted into the code editor. If symbol below cursor is a procedure declaration, inserted snippet will contail all procedure parameters. This functionality can be turned off and on by changing "alOutline.docCommentsType" setting to "none" or "xml".

![Xml Documentation Comments](resources/screen2-xmldoccomments.gif)

### Code analyzers rules viewer

Code analyzers rules viewer can be opened by running "AZ AL Dev Tools: Show Code Analyzers Rules" command. It allows to select one of available code analyzers from a dropdown list and then displays all rules implemented by that analyzer in a table view. It is then possible to select some or all of the rules and create new ruleset file or copy them as ruleset rules or a table to the clipboard using context menu.

![Xml Documentation Comments](resources/screen2-codeanalyzers.png)

### Document syntax visualizer

Document syntax visualizer shows syntax tree created by the AL compiler for the current document. It can be opened by running "AZ AL Dev Tools: Open Document Syntax Visualizer" command. The main purpose of this functionality is to help developers create their own al code analyzers. More information how to create analyzer can be found on my blog here: https://anzwdev.wordpress.com/2019/11/09/custom-al-code-analyzers/

![Document Syntax Visualizer](resources/screen2-syntaxtree.png)

## Contributors

Expand All @@ -112,7 +125,6 @@ This extension has originally been inspired by "Code Outline" extension created
This extension contributes the following settings:

* `alOutline.docCommentsType`: enable documention comments, available values: none, xml
* `alOutline.enableFeaturePreview`: enable preview of future, unstable features
* `alOutline.autorefresh`: refresh code outline tree automatically
* `alOutline.autoGenerateFiles`: automatically generate files for newly created objects
* `alOutline.autoGenerateFileDirectory`: the default directory to create files in, relative to the root directory (e.g., \"Source\<ObjectType\>\")
Expand All @@ -124,6 +136,7 @@ This extension contributes the following settings:
* `alOutline.promptForFilePath`: when generating a new file, ask the user to specify a path relative to the root of the project-folder
* `alOutline.stripNonAlphanumericCharactersFromObjectNames`: always strip non-alphanumeric characters from generated object names
* `alOutline.webClientPort`: web client port number, use 0 for default http/https ports
* `alOutline.openDefinitionInNewTab`: set to true to always open documents in a new tab from "Go to definition" command in "AL Object Browser"

## Known Issues

Expand Down
6 changes: 3 additions & 3 deletions htmlresources/alsymbolsbrowser/js/symbolsbrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ class ObjectBrowser {
});

this._objTree.emptyContent = 'There is nothing to show.';
this._objTree.onNodeSelected = function(node) {
this._objTree.nodeSelected = function(node) {
that.onNodeSelected(node);
};
this._objTree.onShowIdsChanged = function(newVal) {
this._objTree.showIdsChanged = function(newVal) {
this.sendMessage({
command: 'objTreeShowIdsChanged',
value: newVal
});
};

this._symTree.onShowIdsChanged = function(newVal) {
this._symTree.showIdsChanged = function(newVal) {
this.sendMessage({
command: 'symTreeShowIdsChanged',
value: newVal
Expand Down
21 changes: 21 additions & 0 deletions htmlresources/carulesviewer/carulesviewer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<html>
<header>
<script src="##EXTENSIONPATH##/htmlresources/lib/jquery/jquery.min.js"></script>
<script src="##EXTENSIONPATH##/htmlresources/lib/jquery-ui-position/jquery.ui.position.min.js"></script>
<script src="##EXTENSIONPATH##/htmlresources/lib/jquery-context-menu/js/jquery.contextmenu.min.js"></script>
<script src="##EXTENSIONPATH##/htmlresources/lib/filtercompiler/filterCompiler.js"></script>
<script src="##EXTENSIONPATH##/htmlresources/lib/azgridview/azgridview.js"></script>
<script src="##EXTENSIONPATH##/htmlresources/carulesviewer/js/carulesviewer.js"></script>
<script src="##EXTENSIONPATH##/htmlresources/carulesviewer/js/startup.js"></script>
<link rel="stylesheet" type="text/css" href="##EXTENSIONPATH##/htmlresources/lib/jquery-context-menu/css/jquery.contextMenu.css">
<link rel="stylesheet" type="text/css" href="##EXTENSIONPATH##/htmlresources/lib/azgridview/azgridview.css">
<link rel="stylesheet" type="text/css" href="##EXTENSIONPATH##/htmlresources/carulesviewer/css/carulesviewer.css">
</header>

<div id="search">
<div class="searchcaption">Code Analyzer:</div>
<select id="analyzers" class="searchinput" tabindex="1"></select>
</div>
<div id="rules" tabindex="2"></div>

</html>
50 changes: 50 additions & 0 deletions htmlresources/carulesviewer/css/carulesviewer.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
body {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
flex-direction: column;
align-items: stretch;
justify-content: stretch;
padding: 0 !important;
}
input:focus, select:focus, div:focus, button:focus {
outline-color: var(--vscode-focusBorder) !important;
}
input, select {
background: var(--vscode-input-background);
border: 1px solid var(--vscode-panel-border);
color: var(--vscode-input-foreground);
}
input:focus, select:focus, div:focus {
outline-color: var(--vscode-focusBorder) !important;
}

#search .searchinput, #search .ms-options-wrap {
margin: 5px 0px 5px 5px;
}

#search {
flex: 0 0 30px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: stretch;
padding: 0 5px;
}
#search .searchinput, #search .ms-options-wrap {
flex: 1 1 auto;
display: flex;
flex-direction: row;
margin: 5px 0px 5px 5px;
}
#search .searchcaption {
flex: 0 0 auto;
}

#rules {
flex: 1 1 auto;
border: 1px solid var(--vscode-panel-border);
}
133 changes: 133 additions & 0 deletions htmlresources/carulesviewer/js/carulesviewer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
class CARulesViewer {

constructor() {
this._vscode = acquireVsCodeApi();
this._rulesTab = new AZGridView('rules', [
{name:'id', caption:'Id', style: 'width:100px;'},
{name:'title', caption:'Title' },
{name:'defaultSeverity', caption:'Severity', style: 'width:100px' }
]);
this._rulesTab.clipboardEnabled = true;
this._rulesTab.onClipboardCopy = (() => {
this.execRuleCommand('copytable', undefined);
});

this._analyzersSel = document.getElementById('analyzers');

// Handle messages sent from the extension to the webview
window.addEventListener('message', event => {
this.onMessage(event.data);
});

document.getElementById('analyzers').addEventListener('change', event => {
this.onAnalyzerChanged();
});

this.initContextMenu();

this.sendMessage({
command: 'documentLoaded'
});
}

onMessage(message) {
switch (message.command) {
case 'setAnalyzers':
this.setAnalyzers(message.data);
break;
case 'setRules':
this.setRules(message.data);
break;
}
}

sendMessage(data) {
this._vscode.postMessage(data);
}

setAnalyzers(data) {
while (this._analyzersSel.firstChild) {
this._analyzersSel.removeChild(this._analyzersSel.firstChild);
}

if (data) {
for (let i=0; i<data.length; i++) {
let option = document.createElement('option');
option.label = data[i].label;
option.value = data[i].value;
this._analyzersSel.appendChild(option);
}

if (data.length > 0) {
this._analyzersSel.value = data[0].value;
this.onAnalyzerChanged();
}
}
}

setRules(rules) {
if (!rules)
rules = [];
for (let i=0; i<rules.length; i++) {
rules[i].idx = i;
}
this._rulesTab.setData(rules);
}

onAnalyzerChanged() {
this.sendMessage({
command: 'analyzerselected',
name: this._analyzersSel.value
});
}

initContextMenu() {
let me = this;
$('#rules').contextMenu({
selector: 'tr',
callback: (key, options) => {
this.execRuleCommand(key, $(this)[0]);
},
items: {
"newruleset": {name: "New Ruleset File"},
"copyrules": {name: "Copy as Rules"},
"copytable": {name: "Copy as Table"}
}
});
}

execRuleCommand(cmdname, selectedrow) {
//merge path with selectedpaths
let selFound = false;
let mainItem = undefined;

let items = this._rulesTab.getSelected();
let selRules = [];
if (selectedrow)
mainItem = selectedrow.tabData;

if ((items) && (items.length > 0)) {
if (!mainItem)
mainItem = items[0];

for (let i=0; i<items.length; i++) {
if (items[i].idx == mainItem.idx)
selFound = true;
selRules.push(items[i].idx);
}
}

if (mainItem) {
if (!selFound)
selRules.push(mainItem.idx);

this.sendMessage({
command : cmdname,
mainrule : mainItem.idx,
selrules: selRules});
}
}



}
5 changes: 5 additions & 0 deletions htmlresources/carulesviewer/js/startup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var caRulesViewer;

$(function() {
caRulesViewer = new CARulesViewer();
});
23 changes: 21 additions & 2 deletions htmlresources/lib/azgridview/azgridview.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ class AZGridView {
this._loadingText = loadingText;
this._editable = editable;
this._inEditMode = false;
this._headerCreated = false;

this._currRow = -1;
this._currColumn = -1;
this._currDataIdx = -1;
this._minRowIndex = 1;

this.clipboardEnabled = false;
this.onClipboardCopy = undefined;

this.renderTable();
this.initEditor();

Expand Down Expand Up @@ -79,7 +83,7 @@ class AZGridView {
}
}

setData(data) {
setData(data) {
if (this._loadingDiv) {
this._container.removeChild(this._loadingDiv);
this._loadingDiv = undefined;
Expand Down Expand Up @@ -181,6 +185,10 @@ class AZGridView {
}

renderTableHeader() {
if (this._headerCreated)
return;
this._headerCreated = true;

let row = document.createElement('tr');
for (let i=0; i<this._columns.length; i++) {
if (!this._columns[i].hidden) {
Expand Down Expand Up @@ -284,13 +292,17 @@ class AZGridView {
row.className = this._currRowStyle;
else
row.className = this._selStyle;

row.dataSelected = (row.className != '');
}
if (clearSel) {
for (let i=0; i<startIndex; i++) {
this._table.rows[i].className = '';
this._table.rows[i].dataSelected = false;
}
for (let i=endIndex+1; i<this._table.rows.length; i++) {
this._table.rows[i].className = '';
this._table.rows[i].dataSelected = false;
}
}

Expand Down Expand Up @@ -404,6 +416,12 @@ class AZGridView {
handled = true;
}
break;
case 67: //C
if ((this.clipboardEnabled) && (e.ctrlKey) && (!e.shiftKey) && (!e.altKey) && (this.onClipboardCopy)) {
this.onClipboardCopy();
handled = true;
}
break;
case 13:
if (this._editable) {
//this.setCurrCell(this._currRow + 1, this._currColumn, true, false, true, true);
Expand Down Expand Up @@ -568,7 +586,8 @@ class AZGridView {
getSelected() {
let sel = [];
for (let i=this._minRowIndex; i<this._table.rows.length; i++) {
if ((this._table.rows[i].className == this._selStyle) || (this._table.rows[i].className == this._currRowStyle))
//if ((this._table.rows[i].className == this._selStyle) || (this._table.rows[i].className == this._currRowStyle))
if (this._table.rows[i].dataSelected)
sel.push(this._table.rows[i].tabData);
}
return sel;
Expand Down
Loading

0 comments on commit 9efaa12

Please sign in to comment.