Skip to content

Commit

Permalink
Merge pull request #127 from zardoy/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
zardoy authored May 3, 2023
2 parents df3bb76 + 7c8879f commit a8431d3
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 29 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@
"@types/mocha": "^9.1.1",
"@types/pluralize": "^0.0.29",
"@volar/language-server": "1.3.0-alpha.3",
"@volar/language-service": "1.3.0-alpha.3",
"@volar/language-service": "1.5.0",
"@volar/vue-language-core": "^1.2.0-patch.2",
"@vscode/emmet-helper": "^2.8.4",
"@vscode/test-electron": "^2.1.5",
Expand Down
39 changes: 36 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 6 additions & 9 deletions src/vueVolarSupport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,24 @@ export default () => {
if (process.env.PLATFORM !== 'node') return
const handler = () => {
const config = vscode.workspace.getConfiguration('')
if (
!getExtensionSetting('enableVueSupport') ||
!vscode.extensions.getExtension('Vue.volar') ||
isConfigValueChanged('volar.vueserver.configFilePath')
) {
const VOLAR_CONFIG_FILE_SETTING = 'vue.server.configFilePath'
if (!getExtensionSetting('enableVueSupport') || !vscode.extensions.getExtension('Vue.volar') || isConfigValueChanged(VOLAR_CONFIG_FILE_SETTING)) {
return
}

void config.update('volar.vueserver.configFilePath', extensionCtx.asAbsolutePath('./volarConfig.js'), vscode.ConfigurationTarget.Global)
void config.update(VOLAR_CONFIG_FILE_SETTING, extensionCtx.asAbsolutePath('./volarConfig.js'), vscode.ConfigurationTarget.Global)
}

handler()
watchExtensionSettings(['enableVueSupport'], handler)
vscode.extensions.onDidChange(handler)
}

const isConfigValueChanged = (id: string) => {
const isConfigValueChanged = (settingId: string) => {
if (process.env.PLATFORM !== 'web') {
const config = vscode.workspace.getConfiguration('')
const userValue = config.get<string>(id)
if (userValue === config.inspect(id)!.defaultValue) return false
const userValue = config.get<string>(settingId)
if (userValue === config.inspect(settingId)!.defaultValue) return false
// means that value was set by us programmatically, let's update it
// eslint-disable-next-line @typescript-eslint/no-require-imports
if (userValue?.startsWith(require('path').join(extensionCtx.extensionPath, '../..'))) return false
Expand Down
3 changes: 2 additions & 1 deletion typescript/src/completions/functionCompletions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export default (entries: ts.CompletionEntry[]) => {
const { languageService, c, sourceFile, position } = sharedCompletionContext

const methodSnippetInsertTextMode = c('methodSnippetsInsertText')
const enableResolvingInsertText = c('enableMethodSnippets') && methodSnippetInsertTextMode !== 'disable'
const nextChar = sourceFile.getFullText().slice(position, position + 1)
const enableResolvingInsertText = !['(', '.', '`'].includes(nextChar) && c('enableMethodSnippets') && methodSnippetInsertTextMode !== 'disable'
const changeKindToFunction = c('experiments.changeKindToFunction')

if (!enableResolvingInsertText && !changeKindToFunction) return
Expand Down
10 changes: 7 additions & 3 deletions typescript/src/constructMethodSnippet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ export default (
if (!containerNode || isTypeNode(containerNode)) return

const checker = languageService.getProgram()!.getTypeChecker()!
const type = symbol ? checker.getTypeOfSymbol(symbol) : checker.getTypeAtLocation(containerNode)
let type = symbol ? checker.getTypeOfSymbol(symbol) : checker.getTypeAtLocation(containerNode)
// give another chance
if (symbol && type['intrinsicName'] === 'error') type = checker.getTypeOfSymbolAtLocation(symbol, containerNode)

if (ts.isIdentifier(containerNode)) containerNode = containerNode.parent
if (ts.isPropertyAccessExpression(containerNode)) containerNode = containerNode.parent

const isNewExpression = ts.isNewExpression(containerNode)
const isNewExpression =
ts.isNewExpression(containerNode) &&
ts.textSpanIntersectsWithPosition(ts.createTextSpanFromBounds(containerNode.expression.pos, containerNode.expression.end), position)
if (!isNewExpression && (type.getProperties().length > 0 || type.getStringIndexType() || type.getNumberIndexType())) {
resolveData.isAmbiguous = true
}
Expand All @@ -34,7 +38,7 @@ export default (
if (signatures.length === 0) return
const signature = signatures[0]!
// probably need to remove check as class can be instantiated inside another class, and don't really see a reason for this check
if (isNewExpression && hasPrivateOrProtectedModifier((signature.getDeclaration() as ts.ConstructorDeclaration).modifiers)) return
if (isNewExpression && hasPrivateOrProtectedModifier((signature.getDeclaration() as ts.ConstructorDeclaration | undefined)?.modifiers)) return
if (signatures.length > 1 && c('methodSnippets.multipleSignatures') === 'empty') {
return ['']
}
Expand Down
24 changes: 13 additions & 11 deletions typescript/src/volarConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
// will be required from ./node_modules/typescript-essential-plugins/index.js
const originalPluginFactory = require('typescript-essential-plugins')

const plugin = (context => {
const plugin = ((context, { typescript: tsModule } = {}) => {
if (!context) throw new Error('Not recieve context')
const { typescript } = context
let configurationHost = context.configurationHost!
configurationHost ??= context['env'].configurationHost
let configurationHost = context.env
if (context['configurationHost']!) configurationHost = context['configurationHost']!
const patchConfig = config => {
return {
...config,
Expand All @@ -17,13 +18,14 @@ const plugin = (context => {
}

if (typescript && configurationHost) {
const ts = tsModule ?? typescript['module']
const plugin = originalPluginFactory({
typescript: typescript.module,
typescript: ts,
})
// todo support vue-specific settings
const originalLsMethods = { ...typescript.languageService }

void configurationHost.getConfiguration<any>('tsEssentialPlugins').then(_configuration => {
void configurationHost.getConfiguration!<any>('tsEssentialPlugins').then(_configuration => {
// if (typescript.languageService[thisPluginMarker]) return
const config = patchConfig(_configuration)
if (!config.enablePlugin) return
Expand All @@ -39,8 +41,8 @@ const plugin = (context => {
}
})

configurationHost.onDidChangeConfiguration(() => {
void configurationHost.getConfiguration<any>('tsEssentialPlugins').then(config => {
configurationHost.onDidChangeConfiguration!(() => {
void configurationHost.getConfiguration!<any>('tsEssentialPlugins').then(config => {
config = patchConfig(config)
plugin.onConfigurationChanged?.(config)
// temporary workaround
Expand All @@ -54,17 +56,17 @@ const plugin = (context => {
console.warn('Failed to activate tsEssentialPlugins, because of no typescript or configurationHost context')
}
return {}
}) satisfies import('@volar/language-service').LanguageServicePlugin
}) satisfies import('@volar/language-service').Service

module.exports = {
plugins: [
c => {
(...args) => {
try {
return plugin(c)
return plugin(...(args as [any]))
} catch (err) {
console.log('TS Essentials error', err)
return {}
}
},
],
}
} /* satisfies import('@volar/language-service').ServiceContext */
8 changes: 8 additions & 0 deletions typescript/test/completions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ describe('Method snippets', () => {
function foo(this: {}) {}
foo/*3*/
// new class
new Something(foo/*301*/)
// contextual type
declare const bar: {
b: (a) => {}
Expand Down Expand Up @@ -173,6 +176,7 @@ describe('Method snippets', () => {
compareMethodSnippetAgainstMarker(markers, 1, null)
compareMethodSnippetAgainstMarker(markers, 2, '()')
compareMethodSnippetAgainstMarker(markers, 3, '(a)')
compareMethodSnippetAgainstMarker(markers, 301, '(a)')
compareMethodSnippetAgainstMarker(markers, 4, '($b)')
compareMethodSnippetAgainstMarker(markers, 5, '(a, b, { d, e: {} }, ...c)')
compareMethodSnippetAgainstMarker(markers, 6, '(a, b, c)')
Expand All @@ -188,13 +192,17 @@ describe('Method snippets', () => {
protected constructor(a) {}
}
class C {}
new A/*1*/
// not sure...
new B/*2*/
new C/*3*/
`)

compareMethodSnippetAgainstMarker(markers, 1, ['a'])
compareMethodSnippetAgainstMarker(markers, 2, null)
compareMethodSnippetAgainstMarker(markers, 3, [])
})

test('Skip trailing void', () => {
Expand Down
2 changes: 1 addition & 1 deletion typescript/test/testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export const fourslashLikeTester = (contents: string, fileName = entrypoint) =>
export const fileContentsSpecialPositions = (contents: string, fileName = entrypoint) => {
const cursorPositions: [number[], number[], number[]] = [[], [], []]
const cursorPositionsOnly: [number[], number[], number[]] = [[], [], []]
const replacement = /\/\*([tf\d]o?)\*\//g
const replacement = /\/\*((t|f|\d+)o?)\*\//g
let currentMatch: RegExpExecArray | null | undefined
while ((currentMatch = replacement.exec(contents))) {
const offset = currentMatch.index
Expand Down

0 comments on commit a8431d3

Please sign in to comment.