Skip to content

Commit

Permalink
Fix missing details about hide/show and prefix
Browse files Browse the repository at this point in the history
Make the LSP internal data type match better the one from sass_api
  • Loading branch information
wkillerud committed Nov 4, 2024
1 parent b08ad95 commit 73d1efc
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 29 deletions.
2 changes: 2 additions & 0 deletions pkgs/sass_language_services/lib/sass_language_services.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ export 'src/file_system_provider.dart'
show FileSystemProvider, ProviderFileStat, ProviderEntryType;

export 'src/language_services.dart' show LanguageServices;

export 'src/features/document_links/stylesheet_document_link.dart';
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ class DocumentLinkVisitor with sass.RecursiveStatementVisitor {
line: node.urlSpan.start.line,
character: node.urlSpan.start.column),
),
alias: node.namespace == null ||
node.url.toString().contains(node.namespace!)
? null
: node.namespace,
namespace: node.namespace,
),
isSassLink
Expand All @@ -47,8 +43,11 @@ class DocumentLinkVisitor with sass.RecursiveStatementVisitor {
line: node.urlSpan.start.line,
character: node.urlSpan.start.column),
),
prefix: node.prefix,
shownVariables: node.shownVariables,
hiddenVariables: node.hiddenVariables,
shownMixinsAndFunctions: node.shownMixinsAndFunctions,
hiddenMixinsAndFunctions: node.hiddenMixinsAndFunctions,
),
isSassLink
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,18 @@ class DocumentLinksFeature extends LanguageFeature {

if (target.startsWith('sass:')) {
// target is not included since this doesn't link to a file on disk
// TODO: https://github.com/sass/dart-sass-language-server/issues/5#issuecomment-2452932807
resolvedLinks.add(StylesheetDocumentLink(
type: link.type,
range: link.range,
alias: link.alias,
data: link.data,
hiddenVariables: link.hiddenVariables,
tooltip: link.tooltip,
namespace: link.namespace,
prefix: link.prefix,
hiddenVariables: link.hiddenVariables,
shownVariables: link.shownVariables,
tooltip: link.tooltip));
hiddenMixinsAndFunctions: link.hiddenMixinsAndFunctions,
shownMixinsAndFunctions: link.shownMixinsAndFunctions));
continue;
}

Expand All @@ -72,15 +75,17 @@ class DocumentLinksFeature extends LanguageFeature {

// lsp.DocumentLink.target is marked as final, so we make a new one
resolvedLinks.add(StylesheetDocumentLink(
type: link.type,
target: resolved,
range: link.range,
data: link.data,
tooltip: link.tooltip,
alias: link.alias,
namespace: link.namespace,
prefix: link.prefix,
hiddenVariables: link.hiddenVariables,
shownVariables: link.shownVariables,
type: link.type,
hiddenMixinsAndFunctions: link.hiddenMixinsAndFunctions,
shownMixinsAndFunctions: link.shownMixinsAndFunctions,
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,26 @@ import 'package:lsp_server/lsp_server.dart' as lsp;
enum LinkType { use, forward, import }

class StylesheetDocumentLink extends lsp.DocumentLink {
/// The alias, if any.
///
/// | Link | Value |
/// | ---------------------------- | ----------- |
/// | `@use "./colors"` | `undefined` |
/// | `@use "./colors" as c` | `"c"` |
/// | `@use "./colors" as *` | `"*"` |
/// | `@forward "./colors"` | `undefined` |
/// | `@forward "./colors" as c-*` | `"c"` |
String? alias;
final LinkType type;

String? namespace;

Set<String>? hiddenVariables;

Set<String>? shownVariables;

LinkType type;
final String? namespace;
final String? prefix;
final Set<String>? hiddenVariables;
final Set<String>? shownVariables;
final Set<String>? hiddenMixinsAndFunctions;
final Set<String>? shownMixinsAndFunctions;

StylesheetDocumentLink({
super.data,
required this.type,
required super.range,
super.target,
super.tooltip,
this.alias,
this.namespace,
this.prefix,
this.hiddenVariables,
this.shownVariables,
this.hiddenMixinsAndFunctions,
this.shownMixinsAndFunctions,
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import 'package:sass_language_services/sass_language_services.dart';
import 'package:test/test.dart';

import '../../memory_file_system.dart';
import '../../test_client_capabilities.dart';

final fs = MemoryFileSystem();
final ls = LanguageServices(fs: fs, clientCapabilities: getCapabilities());

void main() {
group('Document links', () {
test('should resolve valid links', () async {
fs.createDocument('\$var: 1px;', uri: 'variables.scss');
fs.createDocument('\$tr: 2px;', uri: 'corners.scss');
fs.createDocument('\$b: #000;', uri: 'colors.scss');

var document = fs.createDocument('''
@use "corners" as *;
@use "variables" as vars;
@forward "colors" as color-* hide \$foo, barfunc;
@forward "./does-not-exist" as foo-* show \$public;
''');

var links = await ls.findDocumentLinks(document);
expect(links.length, 4);

var use = links.where((link) => link.type == LinkType.use);
var forward = links.where((link) => link.type == LinkType.forward);

expect(use.length, 2);
expect(forward.length, 2);

expect(use.last.namespace, 'vars');
expect(use.first.namespace, null,
reason: 'Expected wildcard @use not to have a namespace');

expect(forward.last.shownVariables, {'public'});
expect(forward.first.hiddenVariables, {'foo'});
expect(forward.first.hiddenMixinsAndFunctions, {'barfunc'});
expect(forward.first.prefix, 'color-');
expect(forward.last.prefix, 'foo-');

expect(use.first.target != null, true);
expect(use.last.target != null, true);
expect(forward.first.target != null, true);

expect(forward.last.target != null, true,
reason:
'Expected to have a target even though the file does not exist in our file system.');
});

test('should resolve various relative links', () async {
fs.createDocument('\$var: 1px;', uri: 'upper.scss');
fs.createDocument('\$tr: 2px;', uri: 'middle/middle.scss');
fs.createDocument('\$b: #000;', uri: 'middle/lower/lower.scss');

var document = fs.createDocument('''
@use "../upper";
@use "./middle";
@use "./lower/lower";
''', uri: 'middle/main.scss');

var links = await ls.findDocumentLinks(document);

equals(links.length, 3);
});

test('should not break on circular references', () async {
fs.createDocument('''
@use "./pong"
\$var: ping
''', uri: 'ping.sass');

var document = fs.createDocument('''
@use "./pong"
\$var: ping
''', uri: 'ping.sass');

var links = await ls.findDocumentLinks(document);

expect(links.length, 1);
});

// TODO: tests for partials
// TODO: test for CSS imports (@import 'foo.css')
// TODO: test for Sass imports (with and without string quotes)
});
}
19 changes: 17 additions & 2 deletions pkgs/sass_language_services/test/memory_file_system.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,31 @@ import 'dart:io';
import 'package:path/path.dart';
import 'package:sass_language_services/sass_language_services.dart';

/// Implementation of [FileSystemProvider] for use in automated tests.
class MemoryFileSystem extends FileSystemProvider {
final _storage = <String, TextDocument>{};

/// Make a [TextDocument] with the content.
///
/// Sets the default [languageId] based on the file extension in
/// [uri], which defaults to `index.scss`.
TextDocument createDocument(String content,
{String? uri, String? languageId, int? version}) {
var documentUri =
Uri.file(join(Directory.current.path, uri ?? 'index.scss'));

var document =
TextDocument(documentUri, languageId ?? 'scss', version ?? 1, content);
var language = 'scss';
if (languageId != null) {
language = languageId;
} else if (uri != null) {
language = uri.endsWith('.sass')
? 'sass'
: uri.endsWith('.css')
? 'css'
: 'scss';
}

var document = TextDocument(documentUri, language, version ?? 1, content);

_storage[document.uri.toString()] = document;
return document;
Expand Down
15 changes: 15 additions & 0 deletions pkgs/sass_language_services/test/test_client_capabilities.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:lsp_server/lsp_server.dart';

/// Get a reasonable default for client capabilities for tests.
ClientCapabilities getCapabilities() {
return ClientCapabilities(
textDocument: TextDocumentClientCapabilities(
completion: CompletionClientCapabilities(
completionItem: CompletionClientCapabilitiesCompletionItem(
snippetSupport: true,
documentationFormat: [MarkupKind.Markdown, MarkupKind.PlainText],
),
),
hover: HoverClientCapabilities(
contentFormat: [MarkupKind.Markdown, MarkupKind.PlainText])));
}

0 comments on commit 73d1efc

Please sign in to comment.