I am creating a language server. Specifically, the issue is with completions. I'm returning a big list of completion items but whenever I test my language the completion provider simply will not suggest anything after I type a dot(.) when I'm expecting it to suggest, essentially, class members associated with the symbol left of said dot(.). Don't get me wrong, suggestions work until I type the dot(.) character and then it says, "No Suggestions".
Also, I'm trying to implement this server side and not client side.
EDIT:
Essentially, I'm assembling a big list and returning it.
connection.onInitialize((params: node.InitializeParams) => {
workspaceFolder = params.workspaceFolders![0].uri;
const capabilities = params.capabilities;
// Does the client support the `workspace/configuration` request?
// If not, we fall back using global settings.
hasConfigurationCapability = !!(
capabilities.workspace && !!capabilities.workspace.configuration
);
hasWorkspaceFolderCapability = !!(
capabilities.workspace && !!capabilities.workspace.workspaceFolders
);
hasDiagnosticRelatedInformationCapability = !!(
capabilities.textDocument &&
capabilities.textDocument.publishDiagnostics &&
capabilities.textDocument.publishDiagnostics.relatedInformation
);
capabilities.workspace!.workspaceEdit!.documentChanges = true;
const result: node.InitializeResult = {
capabilities: {
textDocumentSync: node.TextDocumentSyncKind.Incremental,
colorProvider: true,
hoverProvider: true,
definitionProvider: true,
typeDefinitionProvider: true,
referencesProvider: true,
documentHighlightProvider: true,
documentSymbolProvider: true,
workspaceSymbolProvider: true,
// codeActionProvider: true,
codeLensProvider: {
resolveProvider: true,
workDoneProgress: false
},
// Tell the client that this server supports code completion.
completionProvider: {
resolveProvider: true,
workDoneProgress: false,
triggerCharacters: ['.', '/'],
allCommitCharacters: ['.']
},
signatureHelpProvider: {
triggerCharacters: ['('],
retriggerCharacters: [','],
workDoneProgress: false
},
executeCommandProvider: {
commands: ["compile"],
workDoneProgress: false
},
semanticTokensProvider: {
documentSelector: [{ scheme: 'file', language: 'agc' }],
legend: {
tokenTypes: gTokenTypes,
tokenModifiers: gTokenModifiers
},
full: true,
workDoneProgress: false
}
}
};
if (hasWorkspaceFolderCapability) {
result.capabilities.workspace = {
workspaceFolders: {
supported: true
}
};
}
return result;
});
// This handler provides the initial list of the completion items.
connection.onCompletion(
async (params: node.TextDocumentPositionParams): Promise<node.CompletionItem[] | node.CompletionList | undefined> => {
console.log("completion");
let doc = documents.get(params.textDocument.uri);
let list:node.CompletionList = node.CompletionList.create([], true);
list.items = list.items.concat(comp.GetAGKKeywordCompletionItems(), comp.GetAGKCommandCompletionItems(), agkDocs.getALLCompletionItems());
list.items.push(sense.GetCommentSnippetCompletionItem(doc, params.position));
list.items.push(sense.GetCommentSnippetCompletionItem(doc, params.position, true));
console.log("END completion");
return list;
}
);
Related
what am I doing wrong? I'm building an accessible website with NextJS and want to redirect to fitting pages to the plain-language-counterpart. But since they are a different kind of language, their URLs are different, too.
My routes are built like this:
Standard language = my-website.com/about
Plain language = my-website.com/plain-language/about
And I have a switch where I can just change the /plain-language/ part
Now I have these routes:
my-website.com/accessible-webdesign
my-website.com/plain-language/for-disabled-persons
And if I click the switch on the first one, it will link me to my-website.com/plain-language/accessible-webdesign, which doesn't exist! So I used redirects() and also restarted my server to fix this, but it doesn't work. It doesn't redirect and I get a 404 just as before.
Can you check my code and tell me, what I should change to make it work?
Thank you!
This is my next.config.js:
const withBundleAnalyzer = require('#next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
/** #type {import('next').NextConfig} */
const path = require('path');
const withPWA = require('next-pwa')({
dest: 'public',
disable: process.env.NODE_ENV === 'development',
sw: 'sw.js'
})
const nextConfig = {
async redirects(){
return[
{
source: '/plain-language/accessible-webdesign',
destination: '/plain-language/for-disabled-persons',
permanent: 'true'
}
]
},
reactStrictMode: true,
swcMinify: true,
trailingSlash: false,
webpackDevMiddleware: config => {
config.watchOptions = {
poll: 1000,
aggregateTimeout: 300
}
return config
},
sassOptions: {
includePaths: [path.join(__dirname, 'styles')]
},
experimental: {
images: {
layoutRaw: true
}
},
images: {
/*unoptimized: true - for static export!*/
/*deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
formats: ['image/webp']*/
}
}
module.exports = withBundleAnalyzer(withPWA({nextConfig}));
My working solution was from here: https://stackoverflow.com/a/58182678/
I put a middleware.ts in the root-folder (right next to package.json, next.config.js etc).
And I wrote this inside:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export async function middleware(request: NextRequest) {
/* /accessible-webdesign --> /for-disabled-persons */
if (request.nextUrl.pathname.startsWith('/plain-language/accessible-webdesign')) {
return NextResponse.redirect(new URL('/plain-language/for-disabled-persons', request.url));
}
/* /another-url --> /another-redirect */
if (request.nextUrl.pathname.startsWith('/plain-language/another-url')) {
return NextResponse.redirect(new URL('/plain-language/another-redirect', request.url));
}
}
Not as beautiful, but working.
I've just started using mochawesome with Cypress (9.7). Our test structure is basically a number of spec files, each following something like the following format:
describe('(A): description of this spec', () => {
describe ('(B): description of test abc', () => {
before(() => {
// do specific set up bits for this test
})
it('(C): runs test abc', () => {
// do actual test stuff
})
})
})
Where within each spec file there would be a single 'A' describe block, but there can be many 'B' level blocks (each with a single 'C') - done this way because the before block for each 'C' is always different - I couldn't use a beforeEach.
When I run my various spec files, each structured similarly to the above, the mochaewsome output is mostly correct - I get a collapsible block for each spec file at level 'A', each with multiple collapsible blocks at level B, each with test info as expected at level C.
But... The circular charts are only displayed at level B. What I was hoping, was that it might be possible to have aggregated charts at level A, and a further aggregated chart for all the level A blocks.
Not sure I've explained this brilliantly(!), but hopefully someone understands, and can offer a suggestion?!
In cypress-mochawesome-reporter there's an alternative setup using on('after:run') which can perform the aggregation.
In Cypress v9.7.0
// cypress/plugins/index.js
const { beforeRunHook, afterRunHook } = require('cypress-mochawesome-reporter/lib');
const { aggregateResults } = require('./aggregate-mochawesome-report-chart');
module.exports = (on, config) => {
on('before:run', async (details) => {
await beforeRunHook(details);
});
on('after:run', async () => {
aggregateResults(config)
await afterRunHook();
});
};
In Cypress v10+
// cypress.config.js
const { defineConfig } = require('cypress');
const { beforeRunHook, afterRunHook } = require('cypress-mochawesome-reporter/lib');
const { aggregateResults } = require('./aggregate-mochawesome-report-chart');
module.exports = defineConfig({
reporter: 'cypress-mochawesome-reporter',
video: false,
retries: 1,
reporterOptions: {
reportDir: 'test-report',
charts: true,
reportPageTitle: 'custom-title',
embeddedScreenshots: true,
inlineAssets: false,
saveAllAttempts: false,
saveJson: true
},
e2e: {
setupNodeEvents(on, config) {
on('before:run', async (details) => {
await beforeRunHook(details);
});
on('after:run', async () => {
aggregateResults(config)
await afterRunHook();
});
},
},
});
The module to do the aggregation is
// aggregate-mochawesome-reporter-chart.js
const path = require('path');
const fs = require('fs-extra')
function aggregateResults(config) {
const jsonPath = path.join(config.reporterOptions.reportDir , '/.jsons', '\mochawesome.json');
const report = fs.readJsonSync(jsonPath)
const topSuite = report.results[0].suites[0]
aggregate(topSuite)
fs.writeJsonSync(jsonPath, report)
}
function aggregate(suite, level = 0) {
const childSuites = suite.suites.map(child => aggregate(child, ++level))
suite.passes = suite.passes.concat(childSuites.map(child => child.passes)).flat()
suite.failures = suite.failures.concat(childSuites.map(child => child.failures)).flat()
suite.pending = suite.pending.concat(childSuites.map(child => child.pending)).flat()
suite.skipped = suite.skipped.concat(childSuites.map(child => child.skipped)).flat()
if (!suite.tests.length && suite.suites[0].tests.length) {
// trigger chart when to describe has no tests
suite.tests = [
{
"title": "Aggregate of tests",
"duration": 20,
"pass": true,
"context": null,
"err": {},
"uuid": "0",
"parentUUID": suite.uuid,
},
]
}
return suite
}
module.exports = {
aggregateResults
}
The function aggregate() recursively loops down through child suites and adds the test results to the parent.
json files
Note the json file is different at the point where afterRunHook runs and at the end of the test run.
If you have the option saveJson: true set, you will get a final json file in the report directory called index.json.
At the afterRunHook stage the file is mochawesome.json.
Before aggregation
After aggregation
When I open a python file, diagnostics seem to be working fine. Then I navigate to a line with a diagnostic error, press the shortcut to invoke code actions ('<space>ca' in my case) and I get a message 'No code actions available'. I have tried running it for different errors, like the following ones:
b =1 #E225 missing whitespace around operator
from jinja2 import StrictUndefined #'jinja2.StricUndefined' imported but unused
import jjj # import-error: Unable to import 'jjj'
I have tried two LSP servers so far: pyright and pylsp, both gave me the same 'No code actions available'
I've seen a similar question but JavaScript asked here and it suggest installing a plugin but that didn't work for me.
Both Pyright and Pyls don't provide any diagnostic solving code actions like jdtls for java unfortunately...
I would recommend checking out their individual repositories on github for further information and development:
pyls,
pyright
For more insight on what your language server is capable of, run the following command in vim:
:lua print(vim.inspect(vim.lsp.buf_get_clients()[1].resolved_capabilities))
It will output the capabilities of the language server you are attached to in the current buffer.
For example this is the output for Pyright with no special configurations:
{
call_hierarchy = true,
code_action = {
codeActionKinds = { "quickfix", "source.organizeImports" },
workDoneProgress = true
},
code_lens = false,
code_lens_resolve = false,
completion = true,
declaration = false,
document_formatting = false,
document_highlight = {
workDoneProgress = true
},
document_range_formatting = false,
document_symbol = {
workDoneProgress = true
},
execute_command = true,
find_references = {
workDoneProgress = true
},
goto_definition = {
workDoneProgress = true
},
hover = {
workDoneProgress = true
},
implementation = false,
rename = true,
signature_help = true,
signature_help_trigger_characters = { "(", ",", ")" },
text_document_did_change = 2,
text_document_open_close = true,
text_document_save = true,
text_document_save_include_text = false,
text_document_will_save = false,
text_document_will_save_wait_until = false,
type_definition = false,
workspace_folder_properties = {
changeNotifications = false,
supported = false
},
workspace_symbol = {
workDoneProgress = true
}
}
Currently Pyright only supports the organize imports code action.
Keep in mind some lsp's don't provide code actions at all, but generally they do provide the basic needs such as go-to definition/declaration, hover info, documentation, signature help, renaming and references.
I'm trying to populate the value for the agSetColumnFilter, but I'm getting an error that I cannot find anything where in documentation (or anywhere online). Has anyone ever run into this issue?
This is what the column definition looks like:
columnDefs.push({
headerName: col.name,
field: col.name,
def: col,
rowGroup: k < groupedColumnCount ? true : false,
pinned: k < _this.groupBy.length ? 'left' : null,
lockPinned: k < _this.groupBy.length ? true : false,
hide: k < groupedColumnCount ? true : false,
suppressToolPanel: _this.groupBy.length ? true : false,
valueGetter: function(data){
if(data.data){
var def = data.colDef.def;
var value = data.data[data.colDef.field];
if(value){
return value.value;
}else{
return null;
}
}else{
return data.value;
}
},
valueFormatter: function(data){
if(data.data){
var def = data.colDef.def;
var value = data.data[data.colDef.field];
if(!value) return null;
if(value.formatted){
_this.cache[data.colDef.field + value.value] = value.formatted;
}
return value.formatted ? value.formatted : value.value;
}else{
if(_this.cache[data.colDef.field + data.value]){
return _this.cache[data.colDef.field + data.value];
}else{
return data.value;
}
}
},
keyCreator: function(params){
console.log(params);
},
filter: 'agSetColumnFilter',
filterParams: {
values: function (params) {
params.success([{
$uri: 'nhuihi',
value: {
$value: 'some text'
}
}]);
}
}
});
I'm only printing out keyCreator params for now since I don't know what will actually be available in the data. The idea is that I can set values using complex objects returned from the server and display a formatted value instead of a key. This is the error I'm getting.
ag-grid-enterprise.min.noStyle.js:formatted:27684 Uncaught TypeError: Cannot read property 'onFilterValuesReady' of undefined
at t.setFilterValues (ag-grid-enterprise.min.noStyle.js:formatted:27684)
at e.modelUpdatedFunc (ag-grid-enterprise.min.noStyle.js:formatted:27609)
at e.onAsyncValuesLoaded (ag-grid-enterprise.min.noStyle.js:formatted:27917)
at values (comparison-table-v7.js:1253)
at e.createAllUniqueValues (ag-grid-enterprise.min.noStyle.js:formatted:27909)
at new e (ag-grid-enterprise.min.noStyle.js:formatted:27867)
at t.initialiseFilterBodyUi (ag-grid-enterprise.min.noStyle.js:formatted:27608)
at t.init (ag-grid-enterprise.min.noStyle.js:formatted:18945)
at e.initialiseComponent (ag-grid-enterprise.min.noStyle.js:formatted:10602)
at e.createAgGridComponent (ag-grid-enterprise.min.noStyle.js:formatted:10574)
Here's a test case for it as well. I simply modified the example by AG Grid. https://plnkr.co/edit/GURQHP0KKFpJ9kwaU83M?p=preview
If you open up console, you will see an error when you click on Athletes filter.
Also reported on GitHub: https://github.com/ag-grid/ag-grid/issues/2829
If you need to configure filter values without async requests
filterParams: {
values: getFilterValuesData()
}
getFilterValuesData(){
//data preparation
//little bit modified sample to present that you can handle your logic here
let data = [];
[
'John Joe Nevin',
'Katie Taylor',
'Paddy Barnes',
'Kenny Egan',
'Darren Sutherland',
'Margaret Thatcher',
'Tony Blair',
'Ronald Regan',
'Barack Obama'
].forEach(i=>{
data.push(i);
});
return data;
}
If it requires to make an async request for data preparation you can use callback function:
filterParams: {
values: (params)=>{
setTimeout(()=>{ -- setTimeout on this case only for async request imitation
params.success(['value 1', 'value 2'])
}, 5000)
}
}
Notice: params.success(...) should be used only with an async request
Doc: ag-grid Asynchronous Values
I want trace changed DOM like mutationobserver in headless chrome.
So I learning puppeteer library, but don’t know how to use do that.
It’s possible to trace DOM change in puppeteer?? thanks
Well,you can inject custom code to the browser.
One way:
await page.evaluate(() => {
const observer = new MutationObserver(
function() {
// communicate with node through console.log method
console.log('__mutation')
}
)
const config = {
attributes: true,
childList: true,
characterData: true,
subtree: true
}
observer.observe(target, config)
})
In your node script:
page.on('console', async (msg) => {
if (msg.text === '__mutation') {
// do something...
}
})