mirror of https://github.com/Wilfred/difftastic/
fixes and tests
parent
f95876f0ed
commit
5e5d9533b5
@ -0,0 +1,461 @@
|
||||
let tree;
|
||||
|
||||
(async () => {
|
||||
const CAPTURE_REGEX = /@\s*([\w\._-]+)/g;
|
||||
const COLORS_BY_INDEX = [
|
||||
'blue',
|
||||
'chocolate',
|
||||
'darkblue',
|
||||
'darkcyan',
|
||||
'darkgreen',
|
||||
'darkred',
|
||||
'darkslategray',
|
||||
'dimgray',
|
||||
'green',
|
||||
'indigo',
|
||||
'navy',
|
||||
'red',
|
||||
'sienna',
|
||||
];
|
||||
|
||||
const scriptURL = document.currentScript.getAttribute('src');
|
||||
|
||||
const codeInput = document.getElementById('code-input');
|
||||
const languageSelect = document.getElementById('language-select');
|
||||
const loggingCheckbox = document.getElementById('logging-checkbox');
|
||||
const outputContainer = document.getElementById('output-container');
|
||||
const outputContainerScroll = document.getElementById('output-container-scroll');
|
||||
const playgroundContainer = document.getElementById('playground-container');
|
||||
const queryCheckbox = document.getElementById('query-checkbox');
|
||||
const queryContainer = document.getElementById('query-container');
|
||||
const queryInput = document.getElementById('query-input');
|
||||
const updateTimeSpan = document.getElementById('update-time');
|
||||
const languagesByName = {};
|
||||
|
||||
loadState();
|
||||
|
||||
await TreeSitter.init();
|
||||
|
||||
const parser = new TreeSitter();
|
||||
const codeEditor = CodeMirror.fromTextArea(codeInput, {
|
||||
lineNumbers: true,
|
||||
showCursorWhenSelecting: true
|
||||
});
|
||||
|
||||
const queryEditor = CodeMirror.fromTextArea(queryInput, {
|
||||
lineNumbers: true,
|
||||
showCursorWhenSelecting: true
|
||||
});
|
||||
|
||||
const cluster = new Clusterize({
|
||||
rows: [],
|
||||
noDataText: null,
|
||||
contentElem: outputContainer,
|
||||
scrollElem: outputContainerScroll
|
||||
});
|
||||
const renderTreeOnCodeChange = debounce(renderTree, 50);
|
||||
const saveStateOnChange = debounce(saveState, 2000);
|
||||
const runTreeQueryOnChange = debounce(runTreeQuery, 50);
|
||||
|
||||
let languageName = languageSelect.value;
|
||||
let treeRows = null;
|
||||
let treeRowHighlightedIndex = -1;
|
||||
let parseCount = 0;
|
||||
let isRendering = 0;
|
||||
let query;
|
||||
|
||||
codeEditor.on('changes', handleCodeChange);
|
||||
codeEditor.on('viewportChange', runTreeQueryOnChange);
|
||||
codeEditor.on('cursorActivity', debounce(handleCursorMovement, 150));
|
||||
queryEditor.on('changes', debounce(handleQueryChange, 150));
|
||||
|
||||
loggingCheckbox.addEventListener('change', handleLoggingChange);
|
||||
queryCheckbox.addEventListener('change', handleQueryEnableChange);
|
||||
languageSelect.addEventListener('change', handleLanguageChange);
|
||||
outputContainer.addEventListener('click', handleTreeClick);
|
||||
|
||||
handleQueryEnableChange();
|
||||
await handleLanguageChange()
|
||||
|
||||
playgroundContainer.style.visibility = 'visible';
|
||||
|
||||
async function handleLanguageChange() {
|
||||
const newLanguageName = languageSelect.value;
|
||||
if (!languagesByName[newLanguageName]) {
|
||||
const url = `${LANGUAGE_BASE_URL}/tree-sitter-${newLanguageName}.wasm`
|
||||
languageSelect.disabled = true;
|
||||
try {
|
||||
languagesByName[newLanguageName] = await TreeSitter.Language.load(url);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
languageSelect.value = languageName;
|
||||
return
|
||||
} finally {
|
||||
languageSelect.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
tree = null;
|
||||
languageName = newLanguageName;
|
||||
parser.setLanguage(languagesByName[newLanguageName]);
|
||||
handleCodeChange();
|
||||
handleQueryChange();
|
||||
}
|
||||
|
||||
async function handleCodeChange(editor, changes) {
|
||||
const newText = codeEditor.getValue() + '\n';
|
||||
const edits = tree && changes && changes.map(treeEditForEditorChange);
|
||||
|
||||
const start = performance.now();
|
||||
if (edits) {
|
||||
for (const edit of edits) {
|
||||
tree.edit(edit);
|
||||
}
|
||||
}
|
||||
const newTree = parser.parse(newText, tree);
|
||||
const duration = (performance.now() - start).toFixed(1);
|
||||
|
||||
updateTimeSpan.innerText = `${duration} ms`;
|
||||
if (tree) tree.delete();
|
||||
tree = newTree;
|
||||
parseCount++;
|
||||
renderTreeOnCodeChange();
|
||||
runTreeQueryOnChange();
|
||||
saveStateOnChange();
|
||||
}
|
||||
|
||||
async function renderTree() {
|
||||
isRendering++;
|
||||
const cursor = tree.walk();
|
||||
|
||||
let currentRenderCount = parseCount;
|
||||
let row = '';
|
||||
let rows = [];
|
||||
let finishedRow = false;
|
||||
let visitedChildren = false;
|
||||
let indentLevel = 0;
|
||||
|
||||
for (let i = 0;; i++) {
|
||||
if (i > 0 && i % 10000 === 0) {
|
||||
await new Promise(r => setTimeout(r, 0));
|
||||
if (parseCount !== currentRenderCount) {
|
||||
cursor.delete();
|
||||
isRendering--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let displayName;
|
||||
if (cursor.nodeIsMissing) {
|
||||
displayName = `MISSING ${cursor.nodeType}`
|
||||
} else if (cursor.nodeIsNamed) {
|
||||
displayName = cursor.nodeType;
|
||||
}
|
||||
|
||||
if (visitedChildren) {
|
||||
if (displayName) {
|
||||
finishedRow = true;
|
||||
}
|
||||
|
||||
if (cursor.gotoNextSibling()) {
|
||||
visitedChildren = false;
|
||||
} else if (cursor.gotoParent()) {
|
||||
visitedChildren = true;
|
||||
indentLevel--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (displayName) {
|
||||
if (finishedRow) {
|
||||
row += '</div>';
|
||||
rows.push(row);
|
||||
finishedRow = false;
|
||||
}
|
||||
const start = cursor.startPosition;
|
||||
const end = cursor.endPosition;
|
||||
const id = cursor.nodeId;
|
||||
let fieldName = cursor.currentFieldName();
|
||||
if (fieldName) {
|
||||
fieldName += ': ';
|
||||
} else {
|
||||
fieldName = '';
|
||||
}
|
||||
row = `<div>${' '.repeat(indentLevel)}${fieldName}<a class='plain' href="#" data-id=${id} data-range="${start.row},${start.column},${end.row},${end.column}">${displayName}</a> [${start.row}, ${start.column}] - [${end.row}, ${end.column}])`;
|
||||
finishedRow = true;
|
||||
}
|
||||
|
||||
if (cursor.gotoFirstChild()) {
|
||||
visitedChildren = false;
|
||||
indentLevel++;
|
||||
} else {
|
||||
visitedChildren = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (finishedRow) {
|
||||
row += '</div>';
|
||||
rows.push(row);
|
||||
}
|
||||
|
||||
cursor.delete();
|
||||
cluster.update(rows);
|
||||
treeRows = rows;
|
||||
isRendering--;
|
||||
handleCursorMovement();
|
||||
}
|
||||
|
||||
function runTreeQuery(_, startRow, endRow) {
|
||||
if (endRow == null) {
|
||||
const viewport = codeEditor.getViewport();
|
||||
startRow = viewport.from;
|
||||
endRow = viewport.to;
|
||||
}
|
||||
|
||||
codeEditor.operation(() => {
|
||||
const marks = codeEditor.getAllMarks();
|
||||
marks.forEach(m => m.clear());
|
||||
|
||||
if (tree && query) {
|
||||
const captures = query.captures(
|
||||
tree.rootNode,
|
||||
{row: startRow, column: 0},
|
||||
{row: endRow, column: 0},
|
||||
);
|
||||
let lastNodeId;
|
||||
for (const {name, node} of captures) {
|
||||
if (node.id === lastNodeId) continue;
|
||||
lastNodeId = node.id;
|
||||
const {startPosition, endPosition} = node;
|
||||
codeEditor.markText(
|
||||
{line: startPosition.row, ch: startPosition.column},
|
||||
{line: endPosition.row, ch: endPosition.column},
|
||||
{
|
||||
inclusiveLeft: true,
|
||||
inclusiveRight: true,
|
||||
css: `color: ${colorForCaptureName(name)}`
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleQueryChange() {
|
||||
if (query) {
|
||||
query.delete();
|
||||
query.deleted = true;
|
||||
query = null;
|
||||
}
|
||||
|
||||
queryEditor.operation(() => {
|
||||
queryEditor.getAllMarks().forEach(m => m.clear());
|
||||
if (!queryCheckbox.checked) return;
|
||||
|
||||
const queryText = queryEditor.getValue();
|
||||
|
||||
try {
|
||||
query = parser.getLanguage().query(queryText);
|
||||
let match;
|
||||
|
||||
let row = 0;
|
||||
queryEditor.eachLine((line) => {
|
||||
while (match = CAPTURE_REGEX.exec(line.text)) {
|
||||
queryEditor.markText(
|
||||
{line: row, ch: match.index},
|
||||
{line: row, ch: match.index + match[0].length},
|
||||
{
|
||||
inclusiveLeft: true,
|
||||
inclusiveRight: true,
|
||||
css: `color: ${colorForCaptureName(match[1])}`
|
||||
}
|
||||
);
|
||||
}
|
||||
row++;
|
||||
});
|
||||
} catch (error) {
|
||||
const startPosition = queryEditor.posFromIndex(error.index);
|
||||
const endPosition = {
|
||||
line: startPosition.line,
|
||||
ch: startPosition.ch + (error.length || Infinity)
|
||||
};
|
||||
|
||||
if (error.index === queryText.length) {
|
||||
if (startPosition.ch > 0) {
|
||||
startPosition.ch--;
|
||||
} else if (startPosition.row > 0) {
|
||||
startPosition.row--;
|
||||
startPosition.column = Infinity;
|
||||
}
|
||||
}
|
||||
|
||||
queryEditor.markText(
|
||||
startPosition,
|
||||
endPosition,
|
||||
{
|
||||
className: 'query-error',
|
||||
inclusiveLeft: true,
|
||||
inclusiveRight: true,
|
||||
attributes: {title: error.message}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
runTreeQuery();
|
||||
saveQueryState();
|
||||
}
|
||||
|
||||
function handleCursorMovement() {
|
||||
if (isRendering) return;
|
||||
|
||||
const selection = codeEditor.getDoc().listSelections()[0];
|
||||
let start = {row: selection.anchor.line, column: selection.anchor.ch};
|
||||
let end = {row: selection.head.line, column: selection.head.ch};
|
||||
if (
|
||||
start.row > end.row ||
|
||||
(
|
||||
start.row === end.row &&
|
||||
start.column > end.column
|
||||
)
|
||||
) {
|
||||
let swap = end;
|
||||
end = start;
|
||||
start = swap;
|
||||
}
|
||||
const node = tree.rootNode.namedDescendantForPosition(start, end);
|
||||
if (treeRows) {
|
||||
if (treeRowHighlightedIndex !== -1) {
|
||||
const row = treeRows[treeRowHighlightedIndex];
|
||||
if (row) treeRows[treeRowHighlightedIndex] = row.replace('highlighted', 'plain');
|
||||
}
|
||||
treeRowHighlightedIndex = treeRows.findIndex(row => row.includes(`data-id=${node.id}`));
|
||||
if (treeRowHighlightedIndex !== -1) {
|
||||
const row = treeRows[treeRowHighlightedIndex];
|
||||
if (row) treeRows[treeRowHighlightedIndex] = row.replace('plain', 'highlighted');
|
||||
}
|
||||
cluster.update(treeRows);
|
||||
const lineHeight = cluster.options.item_height;
|
||||
const scrollTop = outputContainerScroll.scrollTop;
|
||||
const containerHeight = outputContainerScroll.clientHeight;
|
||||
const offset = treeRowHighlightedIndex * lineHeight;
|
||||
if (scrollTop > offset - 20) {
|
||||
$(outputContainerScroll).animate({scrollTop: offset - 20}, 150);
|
||||
} else if (scrollTop < offset + lineHeight + 40 - containerHeight) {
|
||||
$(outputContainerScroll).animate({scrollTop: offset - containerHeight + 40}, 150);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleTreeClick(event) {
|
||||
if (event.target.tagName === 'A') {
|
||||
event.preventDefault();
|
||||
const [startRow, startColumn, endRow, endColumn] = event
|
||||
.target
|
||||
.dataset
|
||||
.range
|
||||
.split(',')
|
||||
.map(n => parseInt(n));
|
||||
codeEditor.focus();
|
||||
codeEditor.setSelection(
|
||||
{line: startRow, ch: startColumn},
|
||||
{line: endRow, ch: endColumn}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function handleLoggingChange() {
|
||||
if (loggingCheckbox.checked) {
|
||||
parser.setLogger((message, lexing) => {
|
||||
if (lexing) {
|
||||
console.log(" ", message)
|
||||
} else {
|
||||
console.log(message)
|
||||
}
|
||||
});
|
||||
} else {
|
||||
parser.setLogger(null);
|
||||
}
|
||||
}
|
||||
|
||||
function handleQueryEnableChange() {
|
||||
if (queryCheckbox.checked) {
|
||||
queryContainer.style.visibility = '';
|
||||
queryContainer.style.position = '';
|
||||
} else {
|
||||
queryContainer.style.visibility = 'hidden';
|
||||
queryContainer.style.position = 'absolute';
|
||||
}
|
||||
handleQueryChange();
|
||||
}
|
||||
|
||||
function treeEditForEditorChange(change) {
|
||||
const oldLineCount = change.removed.length;
|
||||
const newLineCount = change.text.length;
|
||||
const lastLineLength = change.text[newLineCount - 1].length;
|
||||
|
||||
const startPosition = {row: change.from.line, column: change.from.ch};
|
||||
const oldEndPosition = {row: change.to.line, column: change.to.ch};
|
||||
const newEndPosition = {
|
||||
row: startPosition.row + newLineCount - 1,
|
||||
column: newLineCount === 1
|
||||
? startPosition.column + lastLineLength
|
||||
: lastLineLength
|
||||
};
|
||||
|
||||
const startIndex = codeEditor.indexFromPos(change.from);
|
||||
let newEndIndex = startIndex + newLineCount - 1;
|
||||
let oldEndIndex = startIndex + oldLineCount - 1;
|
||||
for (let i = 0; i < newLineCount; i++) newEndIndex += change.text[i].length;
|
||||
for (let i = 0; i < oldLineCount; i++) oldEndIndex += change.removed[i].length;
|
||||
|
||||
return {
|
||||
startIndex, oldEndIndex, newEndIndex,
|
||||
startPosition, oldEndPosition, newEndPosition
|
||||
};
|
||||
}
|
||||
|
||||
function colorForCaptureName(capture) {
|
||||
const id = query.captureNames.indexOf(capture);
|
||||
return COLORS_BY_INDEX[id % COLORS_BY_INDEX.length];
|
||||
}
|
||||
|
||||
function loadState() {
|
||||
const language = localStorage.getItem("language");
|
||||
const sourceCode = localStorage.getItem("sourceCode");
|
||||
const query = localStorage.getItem("query");
|
||||
const queryEnabled = localStorage.getItem("queryEnabled");
|
||||
if (language != null && sourceCode != null && query != null) {
|
||||
queryInput.value = query;
|
||||
codeInput.value = sourceCode;
|
||||
languageSelect.value = language;
|
||||
queryCheckbox.checked = (queryEnabled === 'true');
|
||||
}
|
||||
}
|
||||
|
||||
function saveState() {
|
||||
localStorage.setItem("language", languageSelect.value);
|
||||
localStorage.setItem("sourceCode", codeEditor.getValue());
|
||||
saveQueryState();
|
||||
}
|
||||
|
||||
function saveQueryState() {
|
||||
localStorage.setItem("queryEnabled", queryCheckbox.checked);
|
||||
localStorage.setItem("query", queryEditor.getValue());
|
||||
}
|
||||
|
||||
function debounce(func, wait, immediate) {
|
||||
var timeout;
|
||||
return function() {
|
||||
var context = this, args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
if (!immediate) func.apply(context, args);
|
||||
};
|
||||
var callNow = immediate && !timeout;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
if (callNow) func.apply(context, args);
|
||||
};
|
||||
}
|
||||
})();
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,507 @@
|
||||
================================
|
||||
big test
|
||||
================================
|
||||
abstract class IOSApp extends ApplicationPackage {
|
||||
IOSApp({required String projectBundleId}) : super(id: projectBundleId);
|
||||
|
||||
@override
|
||||
String get displayName => id;
|
||||
|
||||
String get simulatorBundlePath;
|
||||
|
||||
String get deviceBundlePath;
|
||||
|
||||
/// Directory used by ios-deploy to store incremental installation metadata for
|
||||
/// faster second installs.
|
||||
Directory? get appDeltaDirectory;
|
||||
}
|
||||
|
||||
class BuildableIOSApp extends IOSApp {
|
||||
BuildableIOSApp(this.project, String projectBundleId, String? hostAppBundleName)
|
||||
: _hostAppBundleName = hostAppBundleName,
|
||||
super(projectBundleId: projectBundleId);
|
||||
|
||||
static Future<BuildableIOSApp?> fromProject(IosProject project, BuildInfo? buildInfo) async {
|
||||
final String? hostAppBundleName = await project.hostAppBundleName(buildInfo);
|
||||
final String? projectBundleId = await project.productBundleIdentifier(buildInfo);
|
||||
if (projectBundleId != null) {
|
||||
return BuildableIOSApp(project, projectBundleId, hostAppBundleName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final IosProject project;
|
||||
|
||||
final String? _hostAppBundleName;
|
||||
|
||||
@override
|
||||
String? get name => _hostAppBundleName;
|
||||
|
||||
@override
|
||||
String get simulatorBundlePath => _buildAppPath('iphonesimulator');
|
||||
|
||||
@override
|
||||
String get deviceBundlePath => _buildAppPath('iphoneos');
|
||||
|
||||
@override
|
||||
Directory get appDeltaDirectory => globals.fs.directory(globals.fs.path.join(getIosBuildDirectory(), 'app-delta'));
|
||||
|
||||
// Xcode uses this path for the final archive bundle location,
|
||||
// not a top-level output directory.
|
||||
// Specifying `build/ios/archive/Runner` will result in `build/ios/archive/Runner.xcarchive`.
|
||||
String get archiveBundlePath => globals.fs.path.join(getIosBuildDirectory(), 'archive',
|
||||
_hostAppBundleName == null ? 'Runner' : globals.fs.path.withoutExtension(_hostAppBundleName!));
|
||||
|
||||
// The output xcarchive bundle path `build/ios/archive/Runner.xcarchive`.
|
||||
String get archiveBundleOutputPath =>
|
||||
globals.fs.path.setExtension(archiveBundlePath, '.xcarchive');
|
||||
|
||||
String get ipaOutputPath =>
|
||||
globals.fs.path.join(getIosBuildDirectory(), 'ipa');
|
||||
|
||||
String _buildAppPath(String type) {
|
||||
return globals.fs.path.join(getIosBuildDirectory(), type, _hostAppBundleName);
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program (class_definition (identifier) (superclass (type_identifier))
|
||||
(class_body (declaration (constructor_signature (identifier)
|
||||
(formal_parameter_list (optional_formal_parameters
|
||||
(formal_parameter (type_identifier) (identifier))))) (initializers
|
||||
(initializer_list_entry (arguments (named_argument (label (identifier))
|
||||
(identifier)))))) (marker_annotation (identifier))
|
||||
(method_signature (getter_signature
|
||||
(type_identifier) (identifier))) (function_body (identifier)) (declaration
|
||||
(getter_signature (type_identifier) (identifier))) (declaration
|
||||
(getter_signature (type_identifier) (identifier))) (documentation_comment)
|
||||
(documentation_comment) (declaration (getter_signature (type_identifier) (identifier)))))
|
||||
(class_definition (identifier) (superclass (type_identifier))
|
||||
(class_body (declaration (constructor_signature (identifier)
|
||||
(formal_parameter_list (formal_parameter (constructor_param (this) (identifier)))
|
||||
(formal_parameter (type_identifier) (identifier))
|
||||
(formal_parameter (type_identifier) (identifier))))
|
||||
(initializers (initializer_list_entry (field_initializer (identifier) (identifier)))
|
||||
(initializer_list_entry (arguments (named_argument (label (identifier)) (identifier))))))
|
||||
(method_signature (function_signature (type_identifier) (type_arguments
|
||||
(type_identifier)) (identifier) (formal_parameter_list
|
||||
(formal_parameter (type_identifier) (identifier))
|
||||
|
||||
|
||||
|
||||
(formal_parameter (type_identifier) (identifier)))))
|
||||
(function_body
|
||||
(block
|
||||
(local_variable_declaration
|
||||
(initialized_variable_definition (final_builtin) (type_identifier)
|
||||
(identifier)
|
||||
(unary_expression (await_expression (identifier)
|
||||
(selector (unconditional_assignable_selector
|
||||
(identifier))) (selector (argument_part (arguments (argument (identifier)))))))))
|
||||
(local_variable_declaration (initialized_variable_definition (final_builtin)
|
||||
(type_identifier) (identifier) (unary_expression (await_expression (identifier)
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (argument_part (arguments (argument (identifier)))))))))
|
||||
(if_statement (parenthesized_expression (equality_expression (identifier)
|
||||
(equality_operator) (null_literal))) (block (return_statement (identifier)
|
||||
(selector (argument_part (arguments (argument (identifier)) (argument (identifier))
|
||||
(argument (identifier))))))))
|
||||
(return_statement (null_literal))))
|
||||
(declaration (final_builtin) (type_identifier)
|
||||
(initialized_identifier_list (initialized_identifier (identifier))))
|
||||
(declaration (final_builtin) (type_identifier)
|
||||
(initialized_identifier_list (initialized_identifier (identifier))))
|
||||
(marker_annotation (identifier))
|
||||
(method_signature (getter_signature (type_identifier)
|
||||
(identifier))) (function_body (identifier)) (marker_annotation (identifier)) (method_signature
|
||||
(getter_signature (type_identifier) (identifier))) (function_body (identifier)
|
||||
(selector (argument_part (arguments (argument (string_literal))))))
|
||||
(marker_annotation (identifier))
|
||||
(method_signature (getter_signature (type_identifier) (identifier)))
|
||||
(function_body (identifier)
|
||||
(selector (argument_part (arguments (argument (string_literal))))))
|
||||
(marker_annotation (identifier))
|
||||
(method_signature (getter_signature (type_identifier) (identifier)))
|
||||
(function_body (identifier)
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (argument_part (arguments (argument (identifier)
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (argument_part (arguments (argument (identifier)
|
||||
(selector (argument_part (arguments)))) (argument (string_literal))))))))))
|
||||
(comment) (comment) (comment)
|
||||
(method_signature (getter_signature (type_identifier) (identifier)))
|
||||
(function_body (identifier) (selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (argument_part (arguments (argument (identifier)
|
||||
(selector (argument_part (arguments)))) (argument (string_literal)) (argument (conditional_expression (equality_expression (identifier) (equality_operator) (null_literal)) (string_literal) (identifier) (selector (unconditional_assignable_selector (identifier))) (selector (unconditional_assignable_selector (identifier))) (selector (unconditional_assignable_selector (identifier))) (selector (argument_part (arguments (argument (identifier) (selector))))))))))) (comment) (method_signature (getter_signature (type_identifier) (identifier))) (function_body (identifier) (selector (unconditional_assignable_selector (identifier))) (selector (unconditional_assignable_selector (identifier))) (selector (unconditional_assignable_selector (identifier))) (selector (argument_part (arguments (argument (identifier)) (argument (string_literal)))))) (method_signature (getter_signature (type_identifier) (identifier))) (function_body (identifier) (selector (unconditional_assignable_selector (identifier))) (selector (unconditional_assignable_selector (identifier))) (selector (unconditional_assignable_selector (identifier))) (selector (argument_part (arguments (argument (identifier) (selector (argument_part (arguments)))) (argument (string_literal)))))) (method_signature (function_signature (type_identifier) (identifier) (formal_parameter_list (formal_parameter (type_identifier) (identifier))))) (function_body (block (return_statement (identifier)
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (argument_part (arguments (argument (identifier)
|
||||
(selector (argument_part (arguments)))) (argument (identifier)) (argument (identifier)))))))))))
|
||||
|
||||
=====================================
|
||||
more tests
|
||||
======================================
|
||||
typedef RpcPeerConnectionFunction = Future<vms.VmService> Function(
|
||||
Uri uri, {
|
||||
required Duration timeout,
|
||||
});
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(type_alias
|
||||
(type_identifier)
|
||||
(function_type (type_identifier)
|
||||
(type_arguments (type_identifier) (type_identifier))
|
||||
(parameter_type_list
|
||||
(normal_parameter_type
|
||||
(typed_identifier
|
||||
(type_identifier) (identifier)
|
||||
)
|
||||
)
|
||||
(optional_parameter_types
|
||||
(named_parameter_types
|
||||
(typed_identifier (type_identifier) (identifier))))))))
|
||||
|
||||
=======================================
|
||||
more tests2
|
||||
=======================================
|
||||
static bool? _boolAttribute(
|
||||
String resourceId,
|
||||
String name,
|
||||
Map<String, Object?> attributes,
|
||||
String attributeName,
|
||||
) {
|
||||
final Object? value = attributes[attributeName];
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value != 'true' && value != 'false') {
|
||||
throw L10nException(
|
||||
'The "$attributeName" value of the "$name" placeholder in message $resourceId '
|
||||
'must be a boolean value.',
|
||||
);
|
||||
}
|
||||
return value == 'true';
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program (function_signature (type_identifier) (ERROR
|
||||
(identifier)) (identifier)
|
||||
(formal_parameter_list
|
||||
(formal_parameter
|
||||
(type_identifier) (identifier)) (formal_parameter (type_identifier) (identifier))
|
||||
(formal_parameter
|
||||
(type_identifier) (type_arguments (type_identifier) (type_identifier))
|
||||
(identifier))
|
||||
(formal_parameter (type_identifier) (identifier)))
|
||||
)
|
||||
(function_body (block (local_variable_declaration
|
||||
(initialized_variable_definition (final_builtin) (type_identifier) (identifier)
|
||||
(identifier) (selector (unconditional_assignable_selector (identifier)))))
|
||||
(if_statement (parenthesized_expression (equality_expression (identifier) (equality_operator)
|
||||
(null_literal))) (block (return_statement (null_literal))))
|
||||
(if_statement (parenthesized_expression (logical_and_expression
|
||||
(equality_expression (identifier) (equality_operator) (string_literal))
|
||||
(equality_expression (identifier) (equality_operator) (string_literal))))
|
||||
(block (expression_statement (throw_expression (identifier)
|
||||
(selector (argument_part (arguments (argument (string_literal
|
||||
(template_substitution (identifier_dollar_escaped))
|
||||
(template_substitution (identifier_dollar_escaped))
|
||||
(template_substitution (identifier_dollar_escaped)))))))))))
|
||||
(return_statement (equality_expression (identifier) (equality_operator) (string_literal))))))
|
||||
|
||||
===========================================
|
||||
more tests 2
|
||||
===========================================
|
||||
|
||||
/// A doctor validator for both Intellij and Android Studio.
|
||||
abstract class IntelliJValidator extends DoctorValidator {
|
||||
IntelliJValidator(super.title, this.installPath, {
|
||||
required FileSystem fileSystem,
|
||||
required UserMessages userMessages,
|
||||
}) : _fileSystem = fileSystem,
|
||||
_userMessages = userMessages;
|
||||
|
||||
final String installPath;
|
||||
final FileSystem _fileSystem;
|
||||
final UserMessages _userMessages;
|
||||
|
||||
String get version;
|
||||
|
||||
String? get pluginsPath;
|
||||
|
||||
static const Map<String, String> _idToTitle = <String, String>{
|
||||
_ultimateEditionId: _ultimateEditionTitle,
|
||||
_communityEditionId: _communityEditionTitle,
|
||||
};
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(documentation_comment)
|
||||
(class_definition (identifier) (superclass (type_identifier))
|
||||
(class_body (declaration (constructor_signature (identifier)
|
||||
(formal_parameter_list
|
||||
(formal_parameter (super_formal_parameter (super) (identifier)))
|
||||
(formal_parameter (constructor_param (this) (identifier)))
|
||||
(optional_formal_parameters (formal_parameter (type_identifier) (identifier))
|
||||
(formal_parameter (type_identifier) (identifier)))))
|
||||
(initializers (initializer_list_entry (field_initializer (identifier) (identifier)))
|
||||
(initializer_list_entry (field_initializer (identifier) (identifier)))))
|
||||
(declaration (final_builtin) (type_identifier) (initialized_identifier_list
|
||||
(initialized_identifier (identifier)))) (declaration (final_builtin) (type_identifier)
|
||||
(initialized_identifier_list (initialized_identifier (identifier))))
|
||||
(declaration (final_builtin) (type_identifier)
|
||||
(initialized_identifier_list (initialized_identifier (identifier))))
|
||||
(declaration (getter_signature (type_identifier) (identifier)))
|
||||
(declaration (getter_signature (type_identifier) (identifier)))
|
||||
(declaration (const_builtin) (type_identifier) (type_arguments (type_identifier)
|
||||
(type_identifier)) (static_final_declaration_list (static_final_declaration (identifier)
|
||||
(set_or_map_literal (type_arguments (type_identifier) (type_identifier))
|
||||
(pair (identifier) (identifier)) (pair (identifier) (identifier)))))))))
|
||||
|
||||
==============================================
|
||||
more tests 3
|
||||
==============================================
|
||||
|
||||
class _RecompileRequest extends _CompilationRequest {
|
||||
_RecompileRequest(
|
||||
super.completer,
|
||||
this.mainUri,
|
||||
this.invalidatedFiles,
|
||||
this.outputPath,
|
||||
this.packageConfig,
|
||||
this.suppressErrors,
|
||||
{this.additionalSource}
|
||||
);
|
||||
|
||||
Uri mainUri;
|
||||
List<Uri>? invalidatedFiles;
|
||||
String outputPath;
|
||||
PackageConfig packageConfig;
|
||||
bool suppressErrors;
|
||||
final String? additionalSource;
|
||||
|
||||
@override
|
||||
Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async =>
|
||||
compiler._recompile(this);
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(class_definition (identifier)
|
||||
(superclass (type_identifier))
|
||||
(class_body (declaration
|
||||
(constructor_signature (identifier)
|
||||
(formal_parameter_list
|
||||
(formal_parameter (super_formal_parameter (super) (identifier)))
|
||||
(formal_parameter (constructor_param (this) (identifier)))
|
||||
(formal_parameter (constructor_param (this) (identifier)))
|
||||
(formal_parameter (constructor_param (this) (identifier)))
|
||||
(formal_parameter (constructor_param (this) (identifier)))
|
||||
(formal_parameter (constructor_param (this) (identifier)))
|
||||
(optional_formal_parameters
|
||||
(formal_parameter (constructor_param (this) (identifier)))))))
|
||||
(declaration (type_identifier)
|
||||
(initialized_identifier_list (initialized_identifier (identifier))))
|
||||
(declaration (type_identifier) (type_arguments (type_identifier))
|
||||
(initialized_identifier_list (initialized_identifier (identifier))))
|
||||
(declaration (type_identifier) (initialized_identifier_list
|
||||
(initialized_identifier (identifier)))) (declaration (type_identifier)
|
||||
(initialized_identifier_list (initialized_identifier (identifier))))
|
||||
(declaration (type_identifier) (initialized_identifier_list
|
||||
(initialized_identifier (identifier))))
|
||||
(declaration (final_builtin) (type_identifier)
|
||||
(initialized_identifier_list (initialized_identifier (identifier))))
|
||||
(marker_annotation (identifier)) (method_signature
|
||||
(function_signature (type_identifier) (type_arguments (type_identifier))
|
||||
(identifier) (formal_parameter_list (formal_parameter (type_identifier)
|
||||
(identifier))))) (function_body (identifier) (selector
|
||||
(unconditional_assignable_selector (identifier)))
|
||||
(selector (argument_part (arguments (argument (this)))))))))
|
||||
|
||||
|
||||
===============================
|
||||
more tests 4
|
||||
===============================
|
||||
|
||||
bool debugAssertIsValid() {
|
||||
assert(
|
||||
textColor != null
|
||||
&& style != null
|
||||
&& margin != null
|
||||
&& _position != null
|
||||
&& _position.isFinite
|
||||
&& _opacity != null
|
||||
&& _opacity >= 0.0
|
||||
&& _opacity <= 1.0,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
(function_signature (type_identifier) (identifier) (formal_parameter_list))
|
||||
(function_body (block (assert_statement
|
||||
(assertion
|
||||
(logical_and_expression
|
||||
(equality_expression (identifier) (equality_operator) (null_literal))
|
||||
(logical_and_expression
|
||||
(equality_expression (identifier) (equality_operator) (null_literal))
|
||||
(logical_and_expression (equality_expression (identifier) (equality_operator) (null_literal))
|
||||
(logical_and_expression (equality_expression (identifier) (equality_operator) (null_literal))
|
||||
(logical_and_expression (identifier) (selector (unconditional_assignable_selector (identifier)))
|
||||
(logical_and_expression (equality_expression (identifier) (equality_operator) (null_literal))
|
||||
(logical_and_expression
|
||||
(relational_expression (identifier) (relational_operator)
|
||||
(decimal_floating_point_literal))
|
||||
(relational_expression (identifier) (relational_operator) (decimal_floating_point_literal)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
) (return_statement (true)))))
|
||||
|
||||
|
||||
===================================
|
||||
more tests 5
|
||||
===================================
|
||||
|
||||
|
||||
var TextTheme textTheme = TextTheme(error: '');
|
||||
|
||||
---
|
||||
|
||||
|
||||
(program (inferred_type) (type_identifier)
|
||||
(initialized_identifier_list (initialized_identifier (identifier) (identifier)
|
||||
(selector (argument_part (arguments (named_argument (label (identifier)) (string_literal))))))))
|
||||
|
||||
|
||||
===================================
|
||||
more tests 6
|
||||
===================================
|
||||
|
||||
void _layout(ConstraintType constraints) {
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
void layoutCallback() {
|
||||
Widget built;
|
||||
try {
|
||||
built = (widget as ConstrainedLayoutBuilder<ConstraintType>).builder(this, constraints);
|
||||
debugWidgetBuilderValue(widget, built);
|
||||
} catch (e, stack) {
|
||||
built = ErrorWidget.builder(
|
||||
_debugReportException(
|
||||
informationCollector: () => <DiagnosticsNode>[
|
||||
if (kDebugMode)
|
||||
DiagnosticsDebugCreator(DebugCreator(this)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
owner!.buildScope(this, layoutCallback);
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
====================================
|
||||
cascade selector
|
||||
====================================
|
||||
|
||||
|
||||
layer
|
||||
?..link = link
|
||||
..showWhenUnlinked = showWhenUnlinked
|
||||
..linkedOffset = effectiveLinkedOffset
|
||||
..unlinkedOffset = offset;
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
====================================
|
||||
comment selector 1
|
||||
====================================
|
||||
|
||||
// O
|
||||
// / \ O=root
|
||||
// L L L=node with label
|
||||
// / \ C=node with checked
|
||||
// C C* *=node removed next pass
|
||||
//
|
||||
await tester.pumpWidget(Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Stack(),
|
||||
));
|
||||
|
||||
---
|
||||
|
||||
(program
|
||||
|
||||
(comment)
|
||||
(comment)
|
||||
(comment)
|
||||
(comment)
|
||||
(comment)
|
||||
(comment)
|
||||
|
||||
(expression_statement
|
||||
(unary_expression
|
||||
(await_expression (identifier)
|
||||
(selector (unconditional_assignable_selector (identifier)))
|
||||
(selector (argument_part (arguments (argument (identifier)
|
||||
(selector (argument_part
|
||||
(arguments
|
||||
(named_argument (label (identifier)) (identifier)
|
||||
(selector (unconditional_assignable_selector (identifier))))
|
||||
(named_argument (label (identifier)) (identifier) (selector (argument_part (arguments))))
|
||||
)))))))))))
|
||||
|
||||
====================================
|
||||
comment overselected 2
|
||||
====================================
|
||||
|
||||
// }
|
||||
//
|
||||
class Placeholder {
|
||||
Placeholder(this.resourceId, this.name, Map<String, Object?> attributes)
|
||||
: assert(resourceId != null),
|
||||
assert(name != null),
|
||||
example = _stringAttribute(resourceId, name, attributes, 'example'),
|
||||
type = _stringAttribute(resourceId, name, attributes, 'type') ?? 'Object';
|
||||
|
||||
final String resourceId;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(program (comment) (comment) (class_definition (identifier) (class_body (declaration (constructor_signature (identifier) (formal_parameter_list
|
||||
(formal_parameter (constructor_param (this) (identifier))) (formal_parameter (constructor_param (this) (identifier)))
|
||||
(formal_parameter (type_identifier) (type_arguments (type_identifier) (type_identifier)) (identifier)))) (initializers
|
||||
(initializer_list_entry (assertion (equality_expression (identifier) (equality_operator) (null_literal))))
|
||||
(initializer_list_entry (assertion (equality_expression (identifier) (equality_operator) (null_literal))))
|
||||
(initializer_list_entry (field_initializer (identifier) (identifier) (selector (argument_part (arguments (argument (identifier))
|
||||
(argument (identifier)) (argument (identifier)) (argument (string_literal)))))))
|
||||
(initializer_list_entry (field_initializer (identifier)
|
||||
(if_null_expression (identifier) (selector (argument_part (arguments (argument (identifier)) (argument (identifier)) (argument (identifier)) (argument (string_literal))))) (string_literal))))))
|
||||
(declaration (final_builtin) (type_identifier)
|
||||
(initialized_identifier_list (initialized_identifier (identifier)))))))
|
||||
@ -0,0 +1,172 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>tree-sitter THE_LANGUAGE_NAME</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.45.0/codemirror.min.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/clusterize.js/0.18.0/clusterize.min.css">
|
||||
<link rel="icon" type="image/png" href="http://tree-sitter.github.io/tree-sitter/assets/images/favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="http://tree-sitter.github.io/tree-sitter/assets/images/favicon-16x16.png" sizes="16x16" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="playground-container" style="visibility: hidden;">
|
||||
<header>
|
||||
<div class=header-item>
|
||||
<bold>THE_LANGUAGE_NAME</bold>
|
||||
</div>
|
||||
|
||||
<div class=header-item>
|
||||
<label for="logging-checkbox">log</label>
|
||||
<input id="logging-checkbox" type="checkbox"></input>
|
||||
</div>
|
||||
|
||||
<div class=header-item>
|
||||
<label for="query-checkbox">query</label>
|
||||
<input id="query-checkbox" type="checkbox"></input>
|
||||
</div>
|
||||
|
||||
<div class=header-item>
|
||||
<label for="update-time">parse time: </label>
|
||||
<span id="update-time"></span>
|
||||
</div>
|
||||
|
||||
<select id="language-select" style="display: none;">
|
||||
<option value="parser">Parser</option>
|
||||
</select>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div id="input-pane">
|
||||
<div id="code-container">
|
||||
<textarea id="code-input"></textarea>
|
||||
</div>
|
||||
|
||||
<div id="query-container" style="visibility: hidden; position: absolute;">
|
||||
<textarea id="query-input"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="output-container-scroll">
|
||||
<pre id="output-container" class="highlight"></pre>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script
|
||||
src="https://code.jquery.com/jquery-3.3.1.min.js"
|
||||
crossorigin="anonymous">
|
||||
</script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.45.0/codemirror.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/clusterize.js/0.18.0/clusterize.min.js"></script>
|
||||
|
||||
<script>LANGUAGE_BASE_URL = "./";</script>
|
||||
<script src=assets/tree-sitter.js></script>
|
||||
<script src=assets/playground.js></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#playground-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
header {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
padding: 20px;
|
||||
height: 60px;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#input-pane {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#code-container, #query-container {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-right: 1px solid #aaa;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
#output-container-scroll {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.header-item {
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
#playground-container .CodeMirror {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#output-container-scroll {
|
||||
flex: 1;
|
||||
padding: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#output-container {
|
||||
padding: 0 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#logging-checkbox {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
border-left: 3px solid red;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #040404;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a.highlighted {
|
||||
background-color: #d9d9d9;
|
||||
color: red;
|
||||
border-radius: 3px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.query-error {
|
||||
text-decoration: underline red dashed;
|
||||
-webkit-text-decoration: underline red dashed;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
Binary file not shown.
Loading…
Reference in New Issue